web-dev-qa-db-fra.com

Impossible de récupérer les erreurs de validation d'un formulaire AJAX

J'ai un formulaire Drupal qui doit être soumis via AJAX. Je veux valider la saisie est correcte. Quelques choses se produisent:

  • La méthode validateForm est atteinte
  • Je ne peux pas voir les erreurs dans le formulaire avec getErrors
  • Je souhaite valider l'entrée, et si une erreur se produit, flasher un message sous la forme qu'elle n'est pas valide
  • En cas de succès, je veux remplacer le formulaire par un message de succès (mais ça ne va pas si loin)

Voici mon code de formulaire:

<?php

namespace Drupal\harlib_newsletter_signup\Form;

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

/**
 * Class NewsletterSignup.
 */
class NewsletterSignup extends FormBase {

  public $uniqueIdentifier = 'no_tagline';

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'newsletter_signup_' . $this->uniqueIdentifier;
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    if ($this->uniqueIdentifier == "with_tagline") {
      $show_tagline = TRUE;
    }
    else {
      $show_tagline = FALSE;
    }

    $wrapper = 'ajax-wrapper-' . $this->uniqueIdentifier;

    $form['#prefix'] = '<section class="hl__single-input-form"><div id="' . $wrapper . '">';
    $form['#suffix'] = '</div></section>';

    $form['#attributes']['class'][] = 'hl__single-input-form__form';
    $form['#attributes']['novalidate'] = 'novalidate';

    $form['title'] = [
      '#type' => 'label',
      '#for' => 'edit-email-address',
      '#title' => 'Stay in the know',
      '#attributes' => [
        'class' => [
          'hl__label',
          'hl__label--inline',
        ],
      ],
    ];

    if ($show_tagline) {
      $form['tagline'] = [
        '#markup' => '<div class="hl__single-input-form__helper-text">Sign up for email updates from MySite</div>',
      ];
    }

    $errors = $form_state->getErrors();

    if ($errors = $form_state->getErrors()) {
      $form['errors'] = [
        '#markup' => $errors['email_address'],
      ];
    }

    $form['email_address'] = [
      '#type' => 'email',
      '#size' => NULL,
      '#required' => TRUE,
      '#attributes' => [
        'placeholder' => $this->t('Email'),
        'class' => [
          'hl__input',
          'hl__input--inline',
          'js-is-required',
        ],
        'data-twig-suggestion' => 'newsletter_signup_email',
      ],
      '#prefix' => '<div class="hl__single-input-form__input-group">',
    ];

    $form['submit'] = [
      '#type' => 'button',
      '#value' => $this->t('Sign up'),
      '#submit' => ['::submitForm'],
      '#attributes' => [
        'class' => [
          'hl__button',
          'hl__button--small',
          'hl__button--inline',
        ],
        'data-twig-suggestion' => 'newsletter_signup_submit',
      ],
      '#suffix' => '</div>',
      '#ajax' => [
        'wrapper' => $wrapper,
        'method' => 'replace',
        'callback' => '::ajaxRebuildForm',
        'progress' => [
          '#type' => 'none',
        ],
      ],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $email_value = $form_state->getValue('email_address');

    if (empty($email_value) || !\Drupal::service('email.validator')->isValid($email_value)) {
      $form_state->setError($form['email_address'], $this->t('Please enter a valid email address.'));
    }

    if (mailchimp_is_subscribed('XXXXXXX', $email_value, TRUE)) {
      $form_state->setError($form['email_address'], $this->t('You are already subscribed to our newsletter.'));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $result = mailchimp_subscribe('XXXXXXX', $form_state->getValue('email_address'));

    if (empty($result)) {
      $form_state->setError($form['email_address'], $this->t('You are already subscribed to our newsletter.'));
    }
    else {
      drupal_set_message($this->t('Thank you for subscribing to our newsletter!'));
    }
  }

  public function ajaxRebuildForm(array $form, FormStateInterface $formState) {
    return $form;
  }

}

ajaxRebuildForm est-il nécessaire? Comment puis-je valider cela? setError est-il toujours utilisable dans une soumission ajax?

EDIT: J'ai mis à jour la méthode validateForm pour utiliser AjaxResponse. Rien ne se passe sur mon écran.

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    $email_value = $form_state->getValue('email_address');

    if (empty($email_value) || !\Drupal::service('email.validator')->isValid($email_value)) {
      //$form_state->setError($form['email_address'], $this->t('Please enter a valid email address.'));
      //$form_state->setRebuild();
      $response->addCommand(new CssCommand('.hl__single-input-form__input-group', ['border' => '3px solid red']));
      $response->addCommand(new AlertCommand('Heyoooo'));
      return $response;
    }

    if (mailchimp_is_subscribed('XXXXXXX', $email_value, TRUE)) {
      $form_state->setError($form['email_address'], $this->t('You are already subscribed to our newsletter.'));
    }
  }
3
Kevin

Cela s'est avéré être une combinaison de quelques éléments:

  1. J'utilisais ce formulaire plus d'une fois sur la même page
  2. Il s'agit d'un formulaire AJAX, donc la soumission devait être unique.

Ajouter:

$form['submit_' . $this->uniqueIdentifier] au lieu de $form['submit'] a résolu le problème. Je reçois maintenant des erreurs AJAX sur les deux, et les deux soumettent correctement.

2
Kevin

C'est probablement mailchimp_is_subscribed qui le brise. J'ai essayé le code moi-même avec un léger changement:

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $email_value = $form_state->getValue('email_address');

    if (empty($email_value) || !\Drupal::service('email.validator')->isValid($email_value)) {
      $form_state->setError($form['email_address'], $this->t('Please enter a valid email address.'));
    }

    else {
      if (mailchimp_is_subscribed('XXXXXXX', $email_value, TRUE)) {
        $form_state->setError($form['email_address'], $this->t('You are already subscribed to our newsletter.'));
      }
    }
  }

screen-shot

Si cela ne change pas le comportement sur votre système, changez le thème par défaut et testez-le.

Votre thème n'imprime peut-être pas les erreurs. Si c'est le cas, il se peut que la région en surbrillance des messages soit manquante dans votre modèle. Rechercher {{ page.highlighted }} dans votre thème ou son parent et assurez-vous qu'il est imprimé.

0
awm