Skip to research

Bouton 'ajouter un element' et 'retirer cet element' en ajax pour une custom form drupal 8

Temps de lecture
Environ 3 minutes
Étiquettes

Ce bout de code fait la démonstration de l'utilisation de la class FormBase afin d'implémenter à un élément de Form la fonctionnalité - ajouter un élément - ou - retirer cet élément - en ajax.

<?php

namespace Drupal\module_name\Form;

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

/**
 * Implements the ajax add and remove item form controller.
 *
 * This example demonstrates using ajax callbacks to add people's names to a
 * list of picnic attendees.
 *
 * @see \Drupal\Core\Form\FormBase
 * @see \Drupal\Core\Form\ConfigFormBase
 */
class AjaxAddMoreAndRemoveOneForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'ajax_addmore_andremove_one_form';
  }

  /**
   * Form with 'add more' and 'remove this' buttons.
   *
   * This example shows a button to add another textfield, and
   * a bouton "remove this" to delete specific items.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    // Gather the number of items in the form already.
    // We need a element to started
    $num_names = $form_state->get('num_names');
    // We need a element to started, if not, set it
    if ($num_names === NULL) {
      $num_names = $form_state->set('num_names', [1]);
      $num_names = $form_state->get('num_names');
    }
    // No cache please
    $form['#cache'] = ['max-age' => 0];
    // Mode tree for better experience return $form_state
    $form['#tree'] = TRUE;
    // Start stuff with a description
    $form['description'] = [
      '#type' => 'item',
      '#markup' => $this->t('This example shows an add-more and a remove this item button.'),
    ];
    $form['names_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('People coming to picnic'),
      '#prefix' => '<div id="names-fieldset-wrapper">',
      '#suffix' => '</div>',
    ];
    // Loop needed items form
    foreach ($num_names as $key) {
      $form['names_fieldset'][$key]['name'] = [
        '#type' => 'textfield',
        '#title' => t('Name'),
      ];
      $form['names_fieldset'][$key]['forname'] = [
        '#type' => 'textfield',
        '#title' => t('Forname'),
      ];
      // No bouton remove for the first element
      if ($key != 1) {
        $form['names_fieldset'][$key]['remove_name'] = [
          '#type' => 'submit',
          '#value' => t('RM ' . $key),
          '#submit' => ['::removeCallbackOne'],
          '#ajax' => [
            'callback' => '::addmoreCallback',
            'wrapper' => 'names-fieldset-wrapper',
          ],
        ];
      }
    }
    // Action
    $form['names_fieldset']['actions'] = [
      '#type' => 'actions',
    ];
    // Add
    $form['names_fieldset']['actions']['add_name'] = [
      '#type' => 'submit',
      '#value' => t('Add one more'),
      '#submit' => ['::addOne'],
      '#ajax' => [
        'callback' => '::addmoreCallback',
        'wrapper' => 'names-fieldset-wrapper',
      ],
    ];
    // cache FALSE And Submit
    $form_state->setCached(FALSE);
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];
    // Return FORM
    return $form;
  }

  /**
   * Callback for both ajax-enabled buttons.
   *
   * Selects and returns the fieldset with the names in it.
   */
  public function addmoreCallback(array &$form, FormStateInterface $form_state) {
    return $form['names_fieldset'];
  }

  /**
   * Submit handler for the "add-one-more" button.
   *
   * Increments the max counter and causes a rebuild.
   */
  public function addOne(array &$form, FormStateInterface $form_state) {
    // Store our form state
    $field_deltas_array = $form_state->get('num_names');
    
    // check to see if there is more than one item in our array
    if (count($field_deltas_array) > 0) {
      // Add a new element to our array and set it to our highest value plus one
      $field_deltas_array[] = max($field_deltas_array) + 1;
    }
    else {
      // Set the new array element to 0
      $field_deltas_array[] = 0;
    }
    // Rebuild the field deltas values
    $form_state->set('num_names', $field_deltas_array);
    // Rebuild the form
    $form_state->setRebuild();
  }

  /**
   * Submit handler for the "remove this item" button.
   *
   * Search the triggering element and unset it
   * Clean unset new array and rebuit it
   */
  public function removeCallbackOne(array &$form, FormStateInterface $form_state) {

    // Get the triggering item
    $delta_remove = $form_state->getTriggeringElement()['#array_parents'][1];
    
    // Store our form state
    $field_deltas_array = $form_state->get('num_names');
    
    // Find the key of the item we need to remove
    $key_to_remove = array_search($delta_remove, $field_deltas_array);
    
    // Remove our triggered element
    unset($field_deltas_array[$key_to_remove]);
    // return the reel array
    foreach ($field_deltas_array as $key) {
      $output[] = $key;
    }
    // // Rebuild the field deltas values
    $form_state->set('num_names', $output);
    
    // // Rebuild the form
    $form_state->setRebuild();

  }

  /**
   * Final submit handler.
   *
   * Reports what values were finally set.
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Find output information
    $name = $form_state->getValue(['names_fieldset', 'name']);
    $forname = $form_state->getValue(['names_fieldset', 'forname']);
    $identity = '';
    // Gather the number of items returned by the form.
    $num_names = $form_state->get('num_names')
    // Process each items and format it
    foreach ($num_names as $key) {
      $name = $form_state->getValue(['names_fieldset', $key])['name'];
      $forname = $form_state->getValue(['names_fieldset', $key])['forname'];
      $identity .= $forname.' '.$name . '  ';
    } 
    $identity = explode('  ', $identity);
    // return the output
    $output = t('These people are coming to the picnic: @names', [
      '@names' => implode(', ', $identity),
    ]
    );
    drupal_set_message($output);
  }

}