1

I am currently building a module that parses raw HTML into a webform using YAML, however I am running into an issue where the name='SomeName' on form elements is causing an error in the YAML keys.

The form relies on the name attribute in order to accurately map the data so I need it to be case insensitive. I can force a save programmatically with

$webform = new \Drupal\webform\Entity\Webform::create(
// stuff here
);

$webform->save();

However when someone attempts to edit the form in the UI and saves, there is an error preventing save that comes from docroot/modules/contrib/webform/src/WebformEntityElementsValidator.php

This error prevents saving due to casing errors.
The element key contact_Name on line 1 must contain only lowercase letters, numbers, and underscores.

The element key contact_Name on line 1 must contain only lowercase letters, numbers, and underscores.

I have tried

function MYMODULE_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $forms_array = ['webform_ui_element_form', 'webform_source_form'];
  if (in_array($form_id, $forms_array)) {
    $form['actions']['submit']['#limit_validation_errors'] = [];
    $form['actions']['submit']['#_validate_form'] = FALSE;
  }

}

However it seems that for some reason this prevents saving a new element.

Any help is appreciated.

  • 1
    The error is coming \Drupal\webform\WebformEntityElementsValidator. You would need to override this service and remove the validation rule. – jrockowitz Jun 12 at 14:13
  • This is what I've been missing. I don't know why I couldn't figure it out before. Thank you! – JDDoesDev Jun 12 at 14:36
  • 1
    I just learned how to use service decorators. This is might be the best approach to tweaking/altering the WebformEntityElementsValidator service. phase2technology.com/blog/using-symfony-service – jrockowitz Jun 12 at 20:38
1

I was able to achieve this, thanks to some guidance in the comments, by overriding a service.

This involved work in two custom module files. The first was modules/custom/mymodule/src/MymoduleFormParserServiceProvider.php

Within that file I used ::alter to alter which class is called for a particular service.

<?php

namespace Drupal\mymodule;

use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\Core\DependencyInjection\ServiceProviderInterface;
use Drupal\Core\DependencyInjection\ContainerBuilder;

/**
 * Replace Webform validator service.
 */
class MymoduleServiceProvider extends ServiceProviderBase implements ServiceProviderInterface {

  /**
   * {@inheritdoc}
   */
  public function alter(ContainerBuilder $container) {
    $definition = $container->getDefinition('webform.elements_validator');
    $definition->setClass('Drupal\mymodule\MymoduleWebformElementsValidator');
  }

}

What this does is tell Drupal that when the webform.elements_validator service is called, use the MymoduleWebformElementsValidator class instead.

The second piece of the puzzle was to create that class. I did that by extending the original class WebformEntityElementsValidator with my own MymoduleWebformElementsValidator class and doing the logic there. That way I was able to keep most of the validation from the original, but make the changes to the validate method that were needed.

I was able to find many of the answers after googling override service thanks to the comment on the question by @jrockowitz

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.