3

I have a form where I have a link that opens a modal window with another form(something like adding a block to a region).

I would like to perform the action on the opened/second/modal form during submission as usual but I also want to tell the current window to close the modal and to hit a specific button(which is ajaxified and it will rebuild the form so the changes made via the second form would be visible in the main form - they are based on the same data source).

Is there a way to achieve this with ajax command from the second form?

A good example is View form. When a new window is opened(adding a field, or configuring some part of the View), actions in that window are reflected in the form itself after the window is closed.

1

1 Answer 1

2

I recently had to do something similar, and I took a good amount of time to understand how Drupal 8 ajax works. Here are the steps:

Step 1: Ajaxify the link to open the modal, this is easy and you've probably done it already.

$form['ajaxed_link'] = [
  '#type' => 'link',
  '#title' => $this->t('Click to open the modal'),
  '#url' => Url::fromRoute('route_name', ['route_parameters']),
  '#attributes' => [
    'class' => ['use-ajax'],
    'data-dialog-type' => 'modal',
    'data-dialog-options' => Json::encode([
      'height' => 400,
      'width' => 700
    ]),
  ],

Step 2: Create the form that will open when the #url is called and create a route for it as well. Remember to make the submit button there ajax too, and specify an ajax submit handler using the callback key.

$form['submit'] = array(
  '#type' => 'submit',
  '#value' => t('Ajaxed submit button'),
  '#ajax' => [
    'callback' => [$this, 'ajaxSubmit'],
  ]
);

Step 3: Define a function for the callback and make sure it returns an ajax response with the right commands. The first command closes the modal and the second command invokes the click on the desired button (use the correct jquery-selector).

public function ajaxSubmit(array &$form, FormStateInterface $form_state, Request $request) {
  $response = new AjaxResponse();
  $response->addCommand(new CloseModalDialogCommand());
  $response->addCommand(new InvokeCommand('#jquery-selector', 'click'));
  return $response;
}

Take note that it's a good idea to provide a non-ajax fallback return value from the ajaxSubmit callback for clients where JS is disabled. Do this by setting a form redirect in the regular form submit handler.

public function submitForm(array &$form, FormStateInterface $form_state) {
  ...
  $form_state->setRedirect('route_to_previous_form');
}
4
  • I have tried before that but just in case I'll try again.
    – user21641
    Jan 3, 2016 at 12:50
  • I tried it while writing the answer and it works.
    – Alma
    Jan 3, 2016 at 23:47
  • What happens if the submited modal form throws a validation error? You invoke the "CloseMOdalDIalogCommand" first, so will it close before actually you could see the result?
    – ssibal
    Apr 26, 2017 at 8:52
  • I've not verified, but I don't think the ajaxSubmit() will be called if there is a validation error.
    – Alma
    Apr 26, 2017 at 9:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.