Drupal → Навесить на элемент managed_file свой ajax callback (Как обновить всю форму при загрузки файла в managed_file)

31.01.2024

Пример формы с элементом managed_file, в котором после загрузки/удалении файла обновляется вся форма, а не только сам элемент.

class ExampleForm extends FormBase {
  
  /**
   * {@inheritDoc}
   */
  public function getFormId(): string {
    return 'example_form';
  }
  
  /**
   * {@inheritDoc}
   */
  public function buildForm(array &$form, FormStateInterface $form_state): void {
    $form['#id'] = 'example-form';
  
    $managed_file_element_info = \Drupal::service('element_info')->getInfo('managed_file');
    $form['file'] = [
      '#type' => 'managed_file',
      '#title' => 'File',
      '#upload_location' => 'public://',
      '#process' => array_merge($managed_file_element_info['#process'], [[static::class, 'managedFileProcess']]),
    ];
    
    $form['date'] = [
      '#type' => 'item',
      '#markup' => date('r'),
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => 'Submit',
    ];
    
    return $form;
  }
  
  /**
   * Custom #process callback for managed_file form element.
   */
  public static function managedFileProcess(array &$element, FormStateInterface $form_state, array &$complete_form): array {
    if (isset($element['upload_button'])) {
      $element['upload_button']['#original_ajax'] = $element['upload_button']['#ajax'];
      $element['upload_button']['#ajax'] = [
        'callback' => '::ajaxUpdateForm',
      ];
    }
    if (isset($element['remove_button'])) {
      $element['remove_button']['#original_ajax'] = $element['remove_button']['#ajax'];
      $element['remove_button']['#ajax'] = [
        'callback' => '::ajaxUpdateForm',
      ];
    }

    return $element;
  }
  
  /**
   * Ajax update form.
   */
  public function ajaxUpdateForm(array &$form, FormStateInterface $form_state): AjaxResponse {
    $response = new AjaxResponse();

    if ($form_state->hasAnyErrors()) {
      $form['status_messages'] = [
        '#type' => 'status_messages',
        '#weight' => -1000,
      ];
    }

    $response->addCommand(new ReplaceCommand('#' . $form['#id'], $form));

    return $response;
  }  
}

Фишка в том, что переопределять свойства элемента из его getInfo() метода можно прямо в форме. Поэтому получаем информацию об элементе, добавляем в #process свой callback и в нём меняем внутренности элемента без необходимости реализовывать hook_element_info_alter().

Написанное актуально для
Drupal 8+
Похожие записи

Добавить комментарий