0

I have a simple AJAX form that I can't submit when the form is passed from module to the template in hook_preprocess_page. The same form works fine if sent from controller, it's just that the layout is complicated and I prefer to write the HTML part in the twig file and integrate the form where it fits best.

The form class:

    <?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class SubmissionForm extends FormBase {
  public function getFormId() {
    return 'mymodule_submission_form';
  }

  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['#prefix'] = '<div id="submission-form-wrapper">';
    $form['#suffix'] = '</div>';

    $form['mail'] = array(
      '#title' => 'E-mail',
      '#type' => 'textfield',
      '#required' => TRUE,
    );

    $form['actions'] = array(
      '#type' => 'actions'
    );

    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => 'Submit',
      '#attributes' => array(
        'class' => array(
          'btn',
          'btn-success',
          'use-ajax-submit'
        ),
      ),
      '#ajax' => array(
        'wrapper' => 'submission-form-wrapper',
      )
    );

    return $form;
  }

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

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

The preprocess function:

/**
 * Implements hook_preprocess_HOOK().
 */
function mymodule_preprocess_page(&$vars) {
  if (\Drupal::service('path.matcher')->isFrontPage()) {    
    $vars['page']['submission_form'] = \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\SubmissionForm');
  }
}

The error:

TypeError: Argument 1 passed to Drupal\Core\Ajax\AjaxResponse::setAttachments() must be of the type array, null given, called in /Volumes/Work/Git/myproject/public_html/core/lib/Drupal/Core/Render/MainContent/AjaxRenderer.php on line 56 in Drupal\Core\Ajax\AjaxResponse->setAttachments() (line 37 of /Volumes/Work/Git/myproject/public_html/core/lib/Drupal/Core/Render/AttachmentsTrait.php).

  • it's a fresh Drupal 8.7.10
  • devel and kint as contrib modules enabled
  • core inline form errors enabled
  • the form has only one required textfield and the submit button

Any suggestions on how to fix this?

Thank you!

10
  • I can't identify the specific error but this does not seem like a good way to inject a form into a page. Why not implement a block in your module and add it to the page through the block admin? Commented Nov 26, 2019 at 16:00
  • @trudog I don't see any problem in the way you inject the form. Preprocess is fine, Could you update the code in question to contain the full form class
    – Ziftman
    Commented Nov 26, 2019 at 16:21
  • @Ziftman, I've updated the post with the whole form class.
    – Trudog
    Commented Nov 26, 2019 at 19:24
  • @AlfredArmstrong, since there's a very custom layout, the block admin page won't help me.
    – Trudog
    Commented Nov 26, 2019 at 19:27
  • @trudog The code working fine, I can see the form added to the page, and If I fill it and submit it it disappears as expected, without any error. The logic of the form needs more work but that has nothing to do with the problem you describe
    – Ziftman
    Commented Nov 26, 2019 at 19:48

1 Answer 1

0

The #ajax['wrapper'] replaced with #ajax['wrapper_selector'] that's why the form disappear see this issue:

Try with:

<?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class SubmissionForm extends FormBase {

  public function getFormId() {
    return 'mymodule_submission_form';
  }

  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['#prefix'] = '<div id="submission-form-wrapper">';
    $form['#suffix'] = '</div>';

    $form['mail'] = [
      '#title'    => 'E-mail',
      '#type'     => 'textfield',
      '#required' => TRUE,
    ];

    $form['actions'] = [
      '#type' => 'actions',
    ];

    $form['actions']['submit'] = [
      '#type'       => 'submit',
      '#value'      => 'Submit',
      '#attributes' => [
        'class' => [
          'btn',
          'btn-success',
          'use-ajax-submit',
        ],
      ],
      '#ajax'       => [
        // Change here the wrapper with wrapper_selector
        // 'wrapper' => 'submission-form',
        'wrapper_selector' => '#submission-form-wrapper',
      ],
    ];
    return $form;
  }

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

  public function submitForm(array &$form, FormStateInterface $form_state) {
  }
}
3
  • I would have to patch the core and don't want that for the moment. I've followed what 4k4 suggested and managed to make it work using the standard ajax approach. It seems that 'use-ajax-submit' doesn't work as expected in any situation.
    – Trudog
    Commented Nov 27, 2019 at 12:21
  • You don't need to patch the core, i tested the code above with 'wrapper_selector' => '#submission-form-wrapper', it works for me with no errors.
    – berramou
    Commented Nov 27, 2019 at 12:30
  • I did test without patching. Got unexpected behaviour. For example, required fields didn't get the error class and inline error message didn't show...
    – Trudog
    Commented Nov 27, 2019 at 14:09

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.