0

I have a form that adds a product to the cart.

The form uses AJAX to open a modal when the form is submitted.

I want to show form errors (if any) before the modal opens and avoid opening it if there are errors.

Here's my form submit element:

$form['submit'] = [
  '#type' => 'submit',
  '#value' => $this->t('Submit'),
  '#ajax' => [
    'callback' => '::submitAjaxForm'
  ],
  '#attached' => [
    'library' => ['core/drupal.dialog.ajax'],
  ],
];

My submitAjaxForm:

public function submitAjaxForm(array $form, FormStateInterface $form_state) {
  $response = new AjaxResponse();
  $response->addCommand(new OpenModalDialogCommand(
    $this->t('Product added to cart!'),
    [
      '#theme' => 'some_theme',
    ]
  ));

  return $response;
}

And my submitForm:

public function submitForm(array &$form, FormStateInterface $form_state) {
  // Add product to cart.
}

I have tried by adding this code to the AjaxSubmit but it only shows the error messages once the page has been reloaded.

if ($form_state::hasAnyErrors()) {
  foreach ($form_state->getErrors() as $error) {
    $this->messenger()->addError($error);

    $message = [
      '#theme' => 'status_messages',
      '#message_list' => $this->messenger()->messagesByType(MessengerInterface::TYPE_ERROR),
    ];

    $messages = $this->renderer->render($message);

    $response = new AjaxResponse();
    $response->addCommand(new HtmlCommand('#result-message', $messages));
    $form_state->setRebuild(TRUE);

    return $response;
  }
}

How can I show the errors without having to reload the page?

0

I see two things that stand out to me:

1) Setting the '#name' attribute on the submit button. You should never do that. I've learned over the days that there is always a better way to do whatever you're trying to do when setting the #name attribute, and setting it causes some wonkiness. This may be why your form is not rebuilding.

2) You are rendering your status messages in a D7 way. Use this instead:

$messages = ['#type' => 'status_messages']; $response->addCommand(new PrependCommand('#target-div', \Drupal::service('renderer')->renderRoot($messages))); It looks weird, because the messages aren't being retrieved, but by setting the #type to status messages, Drupal will handle the retrieval in the background. This is probably why you are seeing some funkiness with the messages.

  • I don't set #name on the submit button. – user72672 Sep 3 '19 at 10:10

Your Answer

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