I have a Drupal form that should submit via AJAX. I want to validate the input is correct. A few things are happening:
- The
validateForm
method is being hit - I'm not able to see the errors in the form with
getErrors
- I want to validate the input, and if an error occurs, flash a message in the form that it is invalid
- On success, I want to replace the form with a success message (but its not getting that far)
Here is my form code:
<?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;
}
}
Is ajaxRebuildForm
necessary? How can I validate this? Is setError
still workable in an ajax submit?
EDIT: I've updated the validateForm method to use AjaxResponse. Nothing is happening on my screen.
/**
* {@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.'));
}
}
'ajax-wrapper-' . uniqid()
, it wouldn't work as subsequent builds/submits would have different wrapper IDs.