0

I'm having issues with a managed_form field not beeing initialised after it is introduced via a ajaxcallback in a custom checkout Pane:

/**
 * Provides a custom message pane.
 *
 * @CommerceCheckoutPane(
 *   id = "video_greeting",
 *   label = @Translation("Gift Information"),
 *   default_step = "video_greeting",
 * )
 */
class VideoGreetingPane extends CheckoutPaneBase {

 // ...

 public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
    $form_state->set('uploadPath', 'public://orders/' . $this->order->get('order_id')->getString() . '/');

    // ...

    $pane_form['expandable'] = [
      '#prefix' => '<div id="video-greeting-expandable" class="video-greeting__upload pb-3 ' . ($sendsVideoGreeting ? 'show' : 'hidden') . '">',
      '#suffix' => '</div>',
      '#type' => 'container'
    ];

    $pane_form['expandable']['video'] = [
        '#type' => 'inline_template',
        '#template' => "{% include '@vanity/commerce/video-thumbnail.html.twig'  %}",
        '#context' => [
          'video' => $video,
          'order' => $this->order
        ],
      ];

      $class = get_class($this);

      $pane_form['expandable']['remove'] = [
        '#type' => 'button',
        '#value' => $this->t('Remove'),
        '#name' => 'removeButton',
        '#attributes' => [
          'class' => ['btn', 'btn-remove'],
          'type' => 'button'
        ],
        '#ajax' => [
          'callback' => [$class, 'ajaxRemoveVideoCallback'],
          'event' => 'click',
          'wrapper' => 'video-greeting-expandable',
          'method' => 'replace',
          'progress' => [
            'type' => 'throbber',
            'message' => ''
          ]
        ]
      ];

    // ...

 }

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


    $form['video_greeting']['expandable']['video']['#access'] = false;
    $form['video_greeting']['expandable']['remove']['#access'] = false;


    $form['video_greeting']['expandable']['file'] = [
      '#type' => 'managed_file',
      // '#parents' => array_merge($form['video_greeting']['#parents'], ['file']),
      '#required' => false,
      '#upload_location' => $form_state->get('uploadPath'),
      '#upload_validators' => [
        'file_validate_is_video' => [],
        'file_validate_extensions' => ['mp4'],
      ],
      '#description' => t('Please upload a video file.'),
      '#default_value' => null, // don't need
      '#accept' => 'video/mp4',
    ];

    return $form['video_greeting']['expandable'];
  }

  // ...

}

The ajax replace works fine, but the js-component of the managed file get's not initialized somehow. It stays like this after the replace:

<div id="video-greeting-expandable" class="video-greeting__upload pb-3 show">

  <!-- THEME DEBUG -->
  <!-- THEME HOOK: 'container' -->
  <!-- BEGIN OUTPUT from 'core/modules/system/templates/container.html.twig' -->
  <div data-drupal-selector="edit-patenschaft-video-greeting-expandable" id="edit-patenschaft-video-greeting-expandable--NjypaZO-NI0" class="js-form-wrapper form-wrapper">

    <!-- THEME DEBUG -->
    <!-- THEME HOOK: 'form_element' -->
    <!-- BEGIN OUTPUT from 'themes/custom/vanity/templates/form/form-element.html.twig' -->
    <div class="form-item mb-3 form-item- js-form-item- form-no-label">
        

      <!-- THEME DEBUG -->
      <!-- THEME HOOK: 'file_managed_file' -->
      <!-- BEGIN OUTPUT from 'themes/custom/vanity/templates/form/file-managed-file.html.twig' -->
      <div class="js-form-managed-file form-managed-file">
        <!-- ---- Nothing gets initialized here! --- -->
      </div>

      <!-- END OUTPUT from 'themes/custom/vanity/templates/form/file-managed-file.html.twig' -->


    </div>

    <!-- END OUTPUT from 'themes/custom/vanity/templates/form/form-element.html.twig' -->

  </div>

  <!-- END OUTPUT from 'core/modules/system/templates/container.html.twig' -->

</div>

Any hint would be greatly appreciated.

1 Answer 1

3

You are creating form elements in the Ajax callback. These will not work, as the Drupal settings are created before the Ajax callback is called, and therefore any elements added in the ajax callback do not have their JS settings sent to the browser, and therefore the managed file ajax is not initialized.

You need to add any form elements, including your managed_file element, in a conditional in the form definition. This conditional should check if the form has been submitted, and add the form elements accordingly, in the form definition, NOT the ajax callback.

1
  • Dear @Jaypan, thx a lot for your knowledgeble answer - any chance you could post an example of a "conditional" or a link? The concept is so far new to me.
    – Andreas
    Commented Sep 4, 2022 at 17:38

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.