fortnox-8.x-1.x-dev/src/Element/AddMoreAjax.php

src/Element/AddMoreAjax.php
<?php

namespace Drupal\fortnox\Element;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\FormElement;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\HttpFoundation\Request;

/**
 * Provides the add more functionality dynamically.
 *
 * When this form element it's created, a fieldset with the fields data
 * declared will appear and it will be created add more functionality
 * the fieldset can contain multiple fields or only one field.
 *
 * Properties:
 * - #fields: An array of the fields data containing the field name
 * and the field label used for creating the fields inside of the fieldset.
 * - #fieldset_details: An array containing the machine name of the
 * fieldset and the label.
 *
 *
 * Usage Example:
 * @code
 * $form['example'] = [
 *   '#type' => 'dynamic_add_more',
 *   '#fields' => [
 *                ['field_name => 'example_type', field_label => $this->t('Example type)],
 *                ['field_name => 'example_id', 'field_label => $this->('Example ID')],
 *                ],
 *   '#fieldset_machine_name => 'example_fieldset',
 * @endcode
 *
 * @FormElement("dynamic_add_more")
 */
class AddMoreAjax extends FormElement {

  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    $class = get_class($this);
    return [
      '#fields' => [],
      '#fieldset_details' => [],
      '#process' => [
        [$class, 'processAddMoreFieldset'],
      ],
      '#theme_wrappers' => ['form_element'],
    ];
  }

  /**
   * Manage the 'add more' implementation dynamically.
   */
  public static function processAddMoreFieldset(&$element, FormStateInterface $form_state) {
    $fieldset_name = $element['#fieldset_machine_name'];
    $default_value = isset($element['#default_value']) ? $element['#default_value'] : NULL;
    $fields = $element['#fields'];
    $add_fieldset = [
      '#prefix' => '<div id="' . $fieldset_name . '-fieldset-wrapper">',
      '#suffix' => '</div>',
    ];
    // Add the fieldset prefix and suffix for the ajax callback.
    $element += $add_fieldset;
    if (!empty($default_value)) {
      // Count only the integer keys of the default value array.
      $int_default_values = count(array_filter(array_keys($default_value), 'is_int'));
    }
    // Check if we are on edit case and do have already saved values.
    if (!empty($int_default_values) && empty($form_state->getUserInput())) {
      $number_items = $int_default_values;
    }
    else {
      // Gather the number of values added by fieldset in the form already.
      $number_items = $form_state->get('number_items_' . $fieldset_name);
    }
    // We have to ensure that there is at least one name field.
    if ($number_items === NULL) {
      $form_state->set('number_items_' . $fieldset_name, 1);
      $number_items = 1;
    }
    // Add fields based on the numbers added so far.
    for ($i = 0; $i < $number_items; $i++) {
      foreach ($fields as $field) {
        $element[$i][$field['field_name']] = [
          '#type' => $field['field_type'],
          '#title' => $field['field_label'],
          '#default_value' => isset($default_value[$i]) ? $default_value[$i][$field['field_name']] : '',
        ];
        if ($field['field_type'] == 'select') {
          $element[$i][$field['field_name']]['#options'] = $field['options'];
        }
      }
    }
    $element['actions'] = [
      '#type' => 'actions',
    ];
    $element['actions']['add_more'] = [
      '#type' => 'submit',
      '#value' => 'Add one more',
      '#submit' => ['Drupal\fortnox\Element\AddMoreAjax::addOne'],
      '#name' => $fieldset_name,
      '#ajax' => [
        'callback' => 'Drupal\fortnox\Element\AddMoreAjax::addmoreCallback',
        'wrapper' => $fieldset_name . '-fieldset-wrapper',
        'options' => [
          'query' => [
            'element_parents' => implode('/', $element['#array_parents']),
          ],
        ],
      ],
      '#limit_validation_errors' => [],
    ];
    return $element;
  }

  /**
   * Selects and returns the fieldset with the names in it.
   */
  public static function addmoreCallback(&$element, FormStateInterface $form_state, Request $request) {
    $form_parents = explode('/', $request->query->get('element_parents'));

    // Sanitize form parents before using them.
    $form_parents = array_filter($form_parents, [Element::class, 'child']);

    // Retrieve the element to be rendered.
    return NestedArray::getValue($element, $form_parents);
  }

  /**
   * Increments the max counter and causes a rebuild.
   */
  public static function addOne(&$element, FormStateInterface $form_state) {
    $user_input = $form_state->getUserInput();
    $fieldset_name = $form_state->getTriggeringElement()['#name'];
    $fieldset_user_input = $user_input[$fieldset_name];
    // Get the total number of the user input to set properly the count.
    if (!empty(count($fieldset_user_input))) {
      $add_button = count($fieldset_user_input) + 1;
      $form_state->set('number_items_' . $fieldset_name, $add_button);
    }
    else {
      $number_fieldset = $form_state->get('number_items_' . $fieldset_name);
      $add_button = $number_fieldset + 1;
      $form_state->set('number_items_' . $fieldset_name, $add_button);
    }
    $form_state->setRebuild();
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc