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!

  • 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? – Alfred Armstrong Nov 26 '19 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 Nov 26 '19 at 16:21
  • @Ziftman, I've updated the post with the whole form class. – Trudog Nov 26 '19 at 19:24
  • @AlfredArmstrong, since there's a very custom layout, the block admin page won't help me. – Trudog Nov 26 '19 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 Nov 26 '19 at 19:48
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) {
  }
}
  • 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 Nov 27 '19 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 Nov 27 '19 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 Nov 27 '19 at 14:09

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.