Score:0

Admin custom configuration form add more field issue

cn flag

I have created below admin custom configuration form by taking a reference of below examples:

  1. https://git.drupalcode.org/project/examples/-/blob/8.x-1.x/form_api_example/src/Form/AjaxAddMore.php
  2. How do I add a "Add more" button?

My custom form is rendered correctly on first time load but when i click on "Add Product" button nothing happen. As per example the form should rebuild again and prepend the fields. I assume here it could be possible due to something deprecated in Drupal 9 as all above examples are working fine in Drupal 8.

How can I correctly add the Add more button?

<?php

namespace Drupal\commerce_product_quantity\Form;

use Drupal;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Configure commerce_product_quantity settings for this site.
 */
class SettingsForm extends ConfigFormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string
  {
    return 'commerce_product_quantity_settings';
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames(): array
  {
    return ['commerce_product_quantity.settings'];
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array
  {
    /* Fetch All Products */
    $result = Drupal::entityQuery('commerce_product')
      ->execute();
    $titles = array('none' => "- Select -");

    foreach ($result as $product_id) {
      $entity_manager = \Drupal::entityTypeManager();
      $product = $entity_manager->getStorage('commerce_product')->load($product_id);
      $titles[$product->product_id->value] = $product->get('title')->value;
    }

    $field_count = $form_state->get('fields_count');
    $form['#tree'] = TRUE;
    $form['product_quantity_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Products With Total Allowed Quantity'),
      '#attributes' => ['id' => 'product-fieldset-wrapper'],
    ];

    if (empty($field_count)) {
      $form_state->set('fields_count', 1);
      $field_count = 1;
    }

    for ($i = 0; $i < $field_count; $i++) {
      $form['product_quantity_fieldset']['product'.$i] = [
        '#type' => 'select',
        '#title' => t('Add Product'),
        '#options' => $titles,
      ];

      $configName = "commerce_product_quantity.settings.".$i;
      $form['product_quantity_fieldset']['quantity'.$i] = [
        '#type' => 'number',
        '#title' => $this->t('Quantity'),
        '#default_value' => $this->config($configName)->get('quantity'),
      ];
    }
    $form['actions'] = [
      '#type' => 'actions',
    ];
    $form['product_quantity_fieldset']['actions']['add_name'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add Product'),
      '#submit' => array('::addOne'),
      '#ajax' => [
        'callback' => '::addmoreCallback',
        'wrapper' => 'product-fieldset-wrapper',
      ],
    ];
    if ($field_count > 1) {
      $form['product_quantity_fieldset']['actions']['remove_name'] = [
        '#type' => 'submit',
        '#value' => $this->t('Remove one'),
        '#submit' => array('::removeOne'),
        '#ajax' => [
          'callback' => '::removeCallback',
          'wrapper' => 'product-fieldset-wrapper',
        ]
      ];
    }
    $form_state->setCached(FALSE);
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

  public function addOne(array &$form, FormStateInterface $form_state) {
    $field_count = $form_state->get('fields_count');
    $add_button = $field_count + 1;

    \Drupal::messenger()->addStatus($add_button);
    $form_state->set('fields_count', $add_button);
    $form_state->setRebuild();
  }

  public function removeOne(array &$form, FormStateInterface $form_state) {
    $field_count = $form_state->get('num_names');
    $add_button = $field_count + 1;
    $form_state->set('num_names', $add_button);
    $form_state->setRebuild(TRUE);
  }

  public function addmoreCallback(array &$form, FormStateInterface $form_state) {
    $add_button = $form_state->get('fields_count');
    return $form['product_quantity_fieldset'];
  }

  public function removeCallback(array &$form, FormStateInterface $form_state) {
    $field_count = $form_state->get('fields_count');
    if ($field_count > 1) {
      $remove_button = $field_count - 1;
      $form_state->set('fields_count', $remove_button);
    }
    $form_state->setRebuild(TRUE);
  }

  public function validateForm(array &$form, FormStateInterface $form_state) {

  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
   
  }
}
Jaypan avatar
de flag
You've set your form to not be cached with `$form_state->setCached(FALSE);`, I believe this will prevent the #ajax from working correctly.
Harshit Thakore avatar
cn flag
The same code posted in my question is working fine. During development, I have used print_r for debug purpose that cause an issue and it's prevent to rebuild the form. I just removed all print_r from my code and it's working fine.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.