Create a popup form in Drupal 8

  1. Add a route record into /modules/my_module/my_module.routing.yml
    • This route indicated the function openForm of openFormController will be executed after you goto the url of http://yourdomain/openForm through browser.
      my_module.openFormController:
        path: 'openForm'
        defaults:
          _controller: '\Drupal\my_module\Controller\openFormController::openForm'
          _title: 'Open Form'
        requirements:
         _permission: 'access content'
      
  2. Create openFormController.php file in the /modules/my_module/src/Controller/ directory.
    <?php
    namespace Drupal\my_module\Controller;
    
    use Symfony\Component\DependencyInjection\ContainerInterface;
    use Drupal\Core\Ajax\AjaxResponse;
    use Drupal\Core\Ajax\OpenModalDialogCommand;
    use Drupal\Core\Controller\ControllerBase;
    use Drupal\Core\Form\FormBuilder;
    
    class openFormController extends ControllerBase{
      /**
      * Returns a simple page.
      *
      * @return array
      *   A simple renderable array.
      */
    
      protected $formBuilder;
      public function __construct(FormBuilder $formBuilder) {
        $this->formBuilder = $formBuilder;
      }
    
      /**
      * {@inheritdoc}
      *
      * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
      *   The Drupal service container.
      *
      * @return static
      */
      public static function create(ContainerInterface $container) {
        return new static(
          $container->get('form_builder')
        );
      }
    
      public function openForm($subdomain) {
        $response = new AjaxResponse();
    
        // Get the modal form using the form builder.
        $modal_form = $this->formBuilder->getForm('Drupal\my_module\Form\MyForm');
    
        // Add an AJAX command to open a modal dialog with the form as the content.
        $response->addCommand(new OpenModalDialogCommand('Form Title', $modal_form, ['width' => '800']));
    
        return $response;
      }
    }
    ?>
  3. Create MyForm.php file in the /modules/my_module/src/Form/ directory.
    • Add a element of 'status_messages' type into function named buildForm,any form error messages will be shown on this element.
    • Create a function named submitModalFormAjax for check whether has any errors before form submission.
    • You can handle the final result by adding some code into the function named submitForm.
       
      <?php
      namespace Drupal\my_module\Form;
      
      use Drupal\Core\Form\FormBase;
      use Drupal\Core\Form\FormStateInterface;
      
      use Drupal\Core\Ajax\AjaxResponse;
      use Drupal\Core\Ajax\OpenModalDialogCommand;
      use Drupal\Core\Ajax\HtmlCommand;
      use Drupal\Core\Ajax\ReplaceCommand;
      
      class MyForm extends FormBase {
        /**
         * {@inheritdoc}
         */
      
        public function getFormId() {
          return 'my_modal_form';
        }
      
        /**
         * {@inheritdoc}
         */
        public function buildForm(array $form, FormStateInterface $form_state) {
             $form['#prefix'] = '<div id="my_form">';
             $form['#suffix'] = '</div>';
      
             // The status messages that will contain any form errors.
             $form['status_messages'] = [
               '#type' => 'status_messages',
               '#weight' => -10,
             ];
      
             $form['my_field1'] = array(
                '#type' => 'textfield',
                '#title' => 'My Field 1:',
                '#maxlength' => 255,
                '#size' => 10,
                '#required' => TRUE
              );
      
             $form['my_field2'] = array(
                '#type' => 'textfield',
                '#title' => 'My Field 2:',
                '#maxlength' => 255,
                '#size' => 10,
                '#required' => TRUE
              );
      
              $form['actions']['#type'] = 'actions';
              $form['actions']['submit'] = [
                '#type' => 'submit',
                '#value' => $this->t('Submit'),
                '#button_type' => 'primary',
                '#ajax' => [
                  'callback' => [$this, 'submitModalFormAjax'],
                  'event' => 'click',
                ],
              ];
      
              return $form;
        }
      
        /**
        * {@inheritdoc}
        */
        public function validateForm(array &$form, FormStateInterface $form_state) {
        }
      
        /**
         * {@inheritdoc}
         */
        public function submitForm(array &$form, FormStateInterface $form_state) {
        }
      
        /**
        * AJAX callback handler that displays any errors or a success message.
        */
        public function submitModalFormAjax(array $form, FormStateInterface $form_state) {
          $response = new AjaxResponse();
          // If there are any form errors, AJAX replace the form.
          if ($form_state->hasAnyErrors()) {
            $response->addCommand(new ReplaceCommand('#my_form', $form));
          }
          else {
            $response->addCommand(new OpenModalDialogCommand("Success!", 'The modal form has been submitted.', ['width' => 700]));
          }
          return $response;
        }
      
      }
      ?>
  4. Finally, you may create a text link and make the form can be open by the users. For create a text link for the form, you can add the following element into any form or any controller.
    public function getPage(Request $request) {
      $element=[];
      $element['#attached']['library'][] = 'core/drupal.dialog.ajax';
      
      $element['open_my_form']=array(
         '#type' => 'link',
         '#title' => 'Open My Form',
         '#url' => Url::fromRoute('my_module.openFormController'),
         '#attributes' => [
               'class' => [
                      'use-ajax',
                      'button',
                ]
         ]
      )
      return $element;
    }