So I have Drupal 8 webform and it uses a multi page wizard. I've noticed that when I hit the previous button, the required fields on the CURRENT page give the JS validation errors saying that the fields are required. How can I turn off validation when the user clicks on the previous button? I am also using the new signature field and I get the same validation error on the first empty required field on the current page when click on the "Reset" button to clear the signature. It seems that any button that is pressed triggers the form validation. I just want the current page to be validated only when pressing the next/submit buttons. Any help would be appreciated.

I am using:
Webform 8.x-5.0-beta14
Drupal version: 8.3.4

Comments

Jaypan’s picture

You'll need to add the following to any buttons in hook_form_alter(), which prevents validation of all fields:

'#limit_validation_errors' => array(),
marek@appnovation.com’s picture

Thank you I added that and it fixed my issue.

For reference i added this:
$form['actions']['wizard_prev']['#limit_validation_errors'] = array();

However, I still get sent back to the previous page when i hit reset on the signature pad. I guess I will open a separate ticket.

Thanks for your help

Edit: Opened a new ticket for the signature pad problem since it doesn't seem related:
https://www.drupal.org/node/2895681

bradflewelling’s picture

Hey there i'm trying to do the same thing with a button however my code just makes my button disappear, any suggestions?

$form['actions']['workflow_application_process_draft']['#limit_validation_errors'] = [];
Jaypan’s picture

Are you sure this is the correct location?

$form['actions']['workflow_application_process_draft']
Kris77’s picture

Which is the code to put in Drupal 8.8.7 ?

sea2709’s picture

Recently, I have a request about skipping required validation in the multi-step form. The required field is only checked in the last page of the form (or when users submit the form).

My solution is to create a new webform handler. In this handler, I override the function validateForm, so I only validate if the next page is the confirm page or review page.

Here is my piece of code

/**
* Required Validation Webform handler.
*
* @WebformHandler(
* id = "required_validation",
* label = @Translation("Required Validation"),
* category = @Translation("Required Validation"),
* description = @Translation("Required Validation."),
* cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
* results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_IGNORED,
* submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_REQUIRED,
* )
*/
class RequiredValidationWebformHandler extends WebformHandlerBase
{
use WebformAjaxElementTrait;

public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerChannelFactoryInterface $logger_factory, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, WebformSubmissionConditionsValidatorInterface $conditions_validator, WebformElementManagerInterface $element_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $logger_factory, $config_factory, $entity_type_manager, $conditions_validator);

$this->elementManager = $element_manager;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('logger.factory'),
$container->get('config.factory'),
$container->get('entity_type.manager'),
$container->get('webform_submission.conditions_validator'),
$container->get('plugin.manager.webform.element')
);
}

public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$webform = $this->getWebform();
$elements = $webform->getElementsInitializedAndFlattened();

$options = [];
foreach ($elements as $element) {
$webform_element = $this->elementManager->getElementInstance($element);
if (!$webform_element->isContainer($element)) {
$webform_key = $element['#webform_key'];
$options[$webform_key] = $webform_element->getAdminLabel($element);
}
}

$form['element'] = [
'#type' => 'fieldset',
'#title' => $this->t('Element settings'),
];

$form['element']['element_key'] = array(
'#type' => 'select',
'#title' => $this->t('Element'),
'#options' => $options,
'#default_value' => $this->configuration['element_key'],
'#required' => TRUE,
'#empty_option' => (empty($this->configuration['element_key'])) ? $this->t('- Select -') : NULL,
);

$form['element']['required_error'] = [
'#type' => 'textfield',
'#title' => $this->t('Required message'),
'#description' => $this->t('If set, this message will be used when a required webform element is empty, instead of the default "Field x is required." message.'),
'#default_value' => $this->configuration['required_error'],
];

return $form;
}

public function defaultConfiguration() {
return [
'element_key' => '',
'required_error' => ''
];
}

public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::submitConfigurationForm($form, $form_state);

$elementValues = $form_state->getValue('element');
$this->configuration['element_key'] = $elementValues['element_key'];
$this->configuration['required_error'] = $elementValues['required_error'];
}

public function validateForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
$pages = $form_state->get('pages');
$page = $form_state->get('current_page');
$next = WebformArrayHelper::getNextKey($pages, $page);
if ($next && ($next === WebformInterface::PAGE_PREVIEW || $next === WebformInterface::PAGE_CONFIRMATION)) {
$conf = $this->getConfiguration();
if (!empty($conf['settings'])) {
$confSettings = $conf['settings'];
$element = $confSettings['element_key'];
$value = $form_state->getValue($element);
if (empty($value)) {
$form_state->setErrorByName($element, $confSettings['required_error']);
}
}
}
}
}