0

I used a dependent dropdown into an Ajax AddMore, so I checked the code of Ajax Examples, class AjaxAddMore and more. I have several versions that all have a problem; on this one, the behavior of the AddMore overwrites the first form.

Does someone with experience have a solution, please?

namespace Drupal\export\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class TestFilteringStep6Form extends FormBase {

  public function getFormId() {
      return 'test_filtering_step6';
  }

  public function buildForm(array $form, FormStateInterface $form_state) {
    $num_of_filter = $form_state->get('counter');
    if ($num_of_filter === NULL) {
      $form_state->set('counter', 1);
      $num_of_filter = 1;
    }

    $form['#tree'] = TRUE;

    for ($i = 1; $i <= $num_of_filter; $i++) {
      $form['filter_fieldset'][$i] = [
        '#type' => 'fieldset',
        '#title' => $this->t('Filtre ' . $num_of_filter . ' :'),
        '#prefix' => '<div id="add-remove-wrapper">',
        '#suffix' => '</div>',
      ];

      $form['filter_fieldset'][$i]['field'] = [
        '#type' => 'select',
        '#options' => ['(Activités) Nom' => '(Activités) Nom', '(Résultats) Score' => '(Résultats) Score'],
        '#empty_option' => $this->t('- Sélection d\'un champs -'),
        '#ajax' => [
          'wrapper' => 'conditiontype-container-wrapper',
          'callback' => '::promptConditionTypeCallback',
        ],
      ];
      $selected_field[$i] = $form_state->getValue(array('filter_fieldset', $i, 'field'));

      // container :
      $form['filter_fieldset'][$i]['conditiontype_container'] = [
        '#type' => 'container',
        '#attributes' => ['id' => 'conditiontype-container-wrapper'],
      ];

      if (!empty($selected_field[$i])) {
        if ($selected_field[$i] == '(Activités) Nom') {
          $form['filter_fieldset'][$i]['conditiontype_container']['type'] = [
            '#type' => 'select',
            '#options' => ['Activité1' => 'Activité1', 'Activité2' => 'Activité2', 'Activité3' => 'Activité3'],
            '#empty_option' => $this->t('- Sélection d\'un type -'),
            '#default_value' => !empty($form_state->getValue(array('filter_fieldset', $i, 'conditiontype_container', 'type'))) ? $form_state->getValue(array('filter_fieldset', $i, 'conditiontype_container', 'type')) : '',
          ];
        }
        if ($selected_field[$i] == '(Résultats) Score') {
          $form['filter_fieldset'][$i]['conditiontype_container']['type'] = [
            '#type' => 'select',
            '#options' => ['Score1' => 'Score1', 'Score2' => 'Score2', 'Score3' => 'Score3'],
            '#empty_option' => $this->t('- Sélection d\'un type -'),
            '#default_value' => !empty($form_state->getValue(array('filter_fieldset', $i, 'conditiontype_container', 'type'))) ? $form_state->getValue(array('filter_fieldset', $i, 'conditiontype_container', 'type')) : '',
          ];
        }

        if ($form_state->get('counter') > 1) {
          $form['filter_fieldset'][$i]['conditiontype_container']['remove_filter'] = [
            '#type' => 'submit',
            '#value' => $this->t('Supprimer le filtre ' . $num_of_filter),
            '#submit' => ['::subtractOneToCounter'],
            '#ajax' => [
              'callback' => '::returnFilterFieldsetCallback',
              'wrapper' => 'add-remove-wrapper',
            ],
          ];
        }
      }
    }
    $form_state->setCached(FALSE);

    $form['actions'] = [
      '#type' => 'actions',
    ];

    $form['actions']['add_filter'] = [
      '#type' => 'submit',
      '#value' => $this->t('Ajouter un filtre'),
      '#submit' => ['::addOneToCounter'],
      '#ajax' => [
        'callback' => '::returnFilterFieldsetCallback',
        'wrapper' => 'add-remove-wrapper',
      ],
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

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

  /**
   * Callback des select
   */
  public function promptConditionTypeCallback(array &$form, FormStateInterface $form_state) {
    $num_of_filter = $form_state->get('counter');
    $form_state->setRebuild();
    return $form['filter_fieldset'][$num_of_filter]['conditiontype_container'];
  }

  /**
   * Callback des boutons add_filter et remove_filter
   */
  public function returnFilterFieldsetCallback(array &$form, FormStateInterface $form_state) {
    return $form['filter_fieldset'];
  }

  public function addOneToCounter(array &$form, FormStateInterface $form_state) {
    $num_of_filter = $form_state->get('counter');
    $form_state->set('counter', $num_of_filter + 1);
    $form_state->setRebuild();
  }

  public function subtractOneToCounter(array &$form, FormStateInterface $form_state) {
    $num_of_filter = $form_state->get('counter');
    if ($num_of_filter > 1) {
      $form_state->set('counter', $num_of_filter - 1);
    }
    $form_state->setRebuild();
  }

  /**
   * Fonction pour remplir le menu déroulant du type.
   */
  public static function getTypeDropdownOptions($selected_field) {
    switch ($selected_field) {
      case '(Activités) Nom':
        $options = ['Activité1' => 'Activité1', 'Activité2' => 'Activité2', 'Activité3' => 'Activité3'];
        break;

      case '(Résultats) Score':
        $options = ['Résultat1' => 'Résultat1', 'Résultat2' => 'Résultat2', 'Résultat3' => 'Résultat3'];
        break;
    }
    return $options;
  }
}

1 Answer 1

0

Finally, here is my solution

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class TestFilteringStep8Form extends FormBase
{

  public function getFormId()
  {
      return 'test_filtering_step8';
  }

  public function buildForm(array $form, FormStateInterface $form_state)
  {

    $num_of_filter = $form_state->get('counter');
    if ($num_of_filter === NULL) {
      $field = $form_state->set('counter', 1);
      $num_of_filter = 1;
    }

    $form['#tree'] = TRUE;

    $form['filter_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Filtres :'),
      '#prefix' => '<div id="add-remove-wrapper">',
      '#suffix' => '</div>',
    ];

    $form['filter_fieldset']['conditiontype_container'] = [
      '#type' => 'container',
      '#attributes' => ['id' => 'conditiontype-container-wrapper'],
    ];

    for ($i = 1; $i <= $num_of_filter; $i++) {

      $form['filter_fieldset']['conditiontype_container']['field'][$i] = [
        '#type' => 'select',
        '#options' => ['(Activités) Nom' => '(Activités) Nom', '(Résultats) Score' => '(Résultats) Score'],
        '#empty_option' => $this->t('- Sélection d\'un champs -'),
        '#ajax' => [
          'callback' => '::promptConditionTypeCallback',
          'wrapper' => 'conditiontype-container-wrapper',
        ],
      ];

      $selected_field = $form_state->getValue(['filter_fieldset', 'conditiontype_container', 'field', $i]);
      $type_options = static::getTypeDropdownOptions($selected_field);

      if (!empty($selected_field)) {
          $form['filter_fieldset']['conditiontype_container']['type'][$i] = [
            '#type' => 'select',
            '#options' => $type_options,
            '#empty_option' => $this->t('- Sélection d\'un type -'),
          ];
      }
    }

    $form['filter_fieldset']['actions'] = [
      '#type' => 'actions',
    ];
    $form['filter_fieldset']['actions']['add_name'] = [
      '#type' => 'submit',
      '#value' => $this->t('Ajouter un filtre'),
      '#submit' => ['::addOneToCounter'],
      '#ajax' => [
        'callback' => '::returnFilterFieldsetCallback',
        'wrapper' => 'add-remove-wrapper',
      ],
    ];
    // If there is more than one name, add the remove button.
    if ($num_of_filter > 1) {
      $form['filter_fieldset']['actions']['remove_name'] = [
        '#type' => 'submit',
        '#value' => $this->t('Supprimer le filtre ' . $num_of_filter),
        '#submit' => ['::subtractOneToCounter'],
        '#ajax' => [
          'callback' => '::returnFilterFieldsetCallback',
          'wrapper' => 'add-remove-wrapper',
        ],
      ];
    }
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

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

  /**
   * Callback des select conditions et type.
   */
  public function promptConditionTypeCallback(array $form, FormStateInterface $form_state)
  {
    return $form['filter_fieldset']['conditiontype_container'];
  }

  /**
   * Callback des boutons add et remove.
   */
  public function returnFilterFieldsetCallback(array &$form, FormStateInterface $form_state)
  {
    return $form['filter_fieldset'];
  }

  /**
   * Incrémente le compteur
   */
  public function addOneToCounter(array &$form, FormStateInterface $form_state)
  {
    $num_of_filter = $form_state->get('counter');
    $add_button = $num_of_filter + 1;
    $form_state->set('counter', $add_button);
    $form_state->setRebuild();
  }

  /**
   * Decrémente le compteur.
   */
  public function subtractOneToCounter(array &$form, FormStateInterface $form_state)
  {
    $num_of_filter = $form_state->get('counter');
    if ($num_of_filter > 1) {
      $remove_button = $num_of_filter - 1;
      $form_state->set('counter', $remove_button);
    }
    $form_state->setRebuild();
  }

  /**
   * Fonction pour remplir le menu déroulant du type.
   */
  public static function getTypeDropdownOptions($selected_field)
  {
    switch ($selected_field) {
      case '(Activités) Nom':
        $options = ['Activité1' => 'Activité1', 'Activité2' => 'Activité2', 'Activité3' => 'Activité3'];
        break;

      case '(Résultats) Score':
        $options = ['Résultat1' => 'Résultat1', 'Résultat2' => 'Résultat2', 'Résultat3' => 'Résultat3'];
        break;
    }
    return $options;
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.