1

I created 2 forms:

dms_gift_voucher/src/Form/GiftVoucherForm.php

  ...

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    ....
    
    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
      '#attributes' => [
        'class' => [
          'use-ajax',
        ],
      ],
      '#ajax' => [
        'callback' => [$this, 'confirmGiftVoucher'],
        'event' => 'click',
      ],
    ];

    // Dialog box dependency
    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';

    return $form;
  }

  ...

  /**
   * Callback for opening the modal form.
   */
  public function confirmGiftVoucher(array $form, FormStateInterface $form_state) {
    $response = new AjaxResponse();

    // Get the modal form using the form builder.
    $modal_form = $this->formBuilder->getForm('Drupal\dms_gift_voucher\Form\GiftVoucherConfirmForm', $form_state->getValues());

    // Add an AJAX command to open a modal dialog with the form as the content.
    $dialog_options = [
      'width' => 'calc(100% - 20px)',
      'dialogClass' => 'modal--gift-voucher-confirm',
    ];
    $response->addCommand(new OpenModalDialogCommand($this->t('Test'), $modal_form, $dialog_options));

    return $response;
  }

dms_gift_voucher/src/Form/GiftVoucherConfirmForm.php

  ...

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $values = []) {
    ...
    
    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Confirm'),
      '#weight' => 100,
      '#attributes' => [
        'class' => [
          'use-ajax',
        ],
      ],
      '#ajax' => [
        'callback' => [$this, 'submitModalFormAjax'],
        'event' => 'click',
      ],
    ];

    // Library
    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';


    return $form;
  }

  ...

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Never called!
  }

  /**
   * {@inheritdoc}
   */
  public function submitModalFormAjax(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    // Never called!
    return $response;
  }

The first form works correct, the submit is called, the ajax callback renders the modal with the 2nd form. But when i submit the 2nd form, nothing happens, no submit, no ajax callback called from the 2nd form.

How can i fix this? Any suggestions.

(Every example of drupal modal forms start with a link trigger with routing, but i find it strange why this approach doesn't work).

EDIT: As suggested in the comments, routing info:

dms_gift_voucher.routing.yml

dms_gift_voucher.gift_voucher_form:
  path: '/dms_gift_voucher/form/gift_voucher'
  defaults:
    _form: '\Drupal\dms_gift_voucher\Form\GiftVoucherForm'
    _title: 'GiftVoucherForm'
  requirements:
    _access: 'TRUE'

dms_gift_voucher.gift_voucher_cofirm_form:
  path: '/dms_gift_voucher/form/gift_voucher_cofirm_form'
  defaults:
    _form: '\Drupal\dms_gift_voucher\Form\GiftVoucherConfirmForm'
    _title: 'GiftVoucherConfirmForm'
  requirements:
    _access: 'TRUE'
2
  • Because of AJAX Drupal needs to know where to submit to. Add a route to your confirmation form, if you don't have one for it already, and tell me its route name so I can give you the solution.
    – No Sssweat
    Oct 24 '20 at 0:25
  • I added the route information .
    – mgoubert
    Oct 24 '20 at 13:27
1

Since you're programmatically setting a modal with

$response->addCommand(new OpenModalDialogCommand($this->t('Test'), $modal_form, $dialog_options));

For the form that is in the modal, Drupal needs to know what URL it should post the AJAX to and be told that its an AJAX request because this only gets set automatically when the url key doesn't have a value.

  '#ajax' => [
    'callback' => [$this, 'submitModalFormAjax'],
    'event' => 'click',
    'url' = \Drupal\Core\Url::fromRoute('dms_gift_voucher.gift_voucher_cofirm_form'),
    'options' => [
      'query' => [
        FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
      ],
    ],
  ];

Side note: The above isn't needed with the HTML way of opening dialog boxes, had you done:

<a class="use-ajax" 
   data-dialog-options="{&quot;width&quot;:600}" 
   data-dialog-type="modal" 
   href="/dms_gift_voucher/form/gift_voucher_cofirm_form">
   Should load Test webform in a Modal
</a>

because it has the URL of the form and knows its an AJAX request from the class name.

4
  • Form is not rebuild when form is return in ajax callback. Rebuild is set to true, wrapper set and $form returned. Any suggestions?
    – mgoubert
    Oct 26 '20 at 9:57
  • Which form doesn't get rebuild? @mgoubert
    – No Sssweat
    Oct 26 '20 at 20:22
  • The ajax forms in drupal 8 are sometimes hard to comprehend. The form_state (getValues()) is correct if ajaxcallback has "return $form" and $form_state->rebuild() is set to TRUE in the submit handler. But if validation error happens, the submit is never called and form_state->geValues() in buildform is empty. Mabey i should make other thread.
    – mgoubert
    Oct 27 '20 at 10:19
  • I'm a bit lost, would be good to see what fields you have in your form and what you have in your callbacks. So yeah make a new question with those details and issue.
    – No Sssweat
    Oct 27 '20 at 10:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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