Commit 128cb262 authored by larowlan's avatar larowlan

Issue #2856950 by dmsmidt, marcvangend, tim.plunkett, andrewmacpherson,...

Issue #2856950 by dmsmidt, marcvangend, tim.plunkett, andrewmacpherson, Lendude, tameeshb, Berdir, xjm, tedbow, Gábor Hojtsy, Sutharsan: Add a possibility to disable inline form errors for a complete form
parent ad1e35c7
......@@ -6,6 +6,7 @@
*/
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\inline_form_errors\RenderElementHelper;
/**
* Implements hook_help().
......@@ -54,6 +55,14 @@ function inline_form_errors_preprocess_datetime_wrapper(&$variables) {
_inline_form_errors_set_errors($variables);
}
/**
* Implements hook_element_info_alter().
*/
function inline_form_errors_element_info_alter(array &$info) {
\Drupal::classResolver()->getInstanceFromDefinition(RenderElementHelper::class)
->alterElementInfo($info);
}
/**
* Populates form errors in the template.
*/
......
......@@ -47,15 +47,23 @@ public function __construct(TranslationInterface $string_translation, LinkGenera
/**
* Loops through and displays all form errors.
*
* To disable inline form errors for an entire form set the
* #disable_inline_form_errors property to TRUE on the top level of the $form
* array:
* @code
* $form['#disable_inline_form_errors'] = TRUE;
* @endcode
* This should only be done when another appropriate accessibility strategy is
* in place.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
protected function displayErrorMessages(array $form, FormStateInterface $form_state) {
// Use the original error display for Quick Edit forms, because in this case
// the errors are already near the form element.
if ($form['#form_id'] === 'quickedit_field_form') {
// Skip generating inline form errors when opted out.
if (!empty($form['#disable_inline_form_errors'])) {
parent::displayErrorMessages($form, $form_state);
return;
}
......
<?php
namespace Drupal\inline_form_errors;
use Drupal\Core\Form\FormStateInterface;
/**
* Provides functionality to process render elements.
*/
class RenderElementHelper {
/**
* Alters the element type info.
*
* @param array $info
* An associative array with structure identical to that of the return value
* of \Drupal\Core\Render\ElementInfoManagerInterface::getInfo().
*/
public function alterElementInfo(array &$info) {
foreach ($info as $element_type => $element_info) {
$info[$element_type]['#process'][] = [static::class, 'processElement'];
}
}
/**
* Process all render elements.
*
* @param array $element
* An associative array containing the properties and children of the
* element. Note that $element must be taken by reference here, so processed
* child elements are taken over into $form_state.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param array $complete_form
* The complete form structure.
*
* @return array
* The processed element.
*/
public static function processElement(array &$element, FormStateInterface $form_state, array &$complete_form) {
// Prevent displaying inline form errors when disabled for the whole form.
if (!empty($complete_form['#disable_inline_form_errors'])) {
$element['#error_no_message'] = TRUE;
}
return $element;
}
}
<?php
namespace Drupal\Tests\inline_form_errors\Kernel;
use Drupal\Core\Form\FormState;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests messages on form elements.
*
* @group InlineFormErrors
*/
class FormElementInlineErrorTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['inline_form_errors'];
/**
* Tests that no inline form errors are shown when disabled for a form.
*/
public function testDisplayErrorMessagesNotInline() {
$form_id = 'test';
$form = [
'#parents' => [],
'#disable_inline_form_errors' => TRUE,
'#array_parents' => [],
];
$form['test'] = [
'#type' => 'textfield',
'#title' => 'Test',
'#parents' => ['test'],
'#id' => 'edit-test',
'#array_parents' => ['test'],
];
$form_state = new FormState();
\Drupal::formBuilder()->prepareForm($form_id, $form, $form_state);
\Drupal::formBuilder()->processForm($form_id, $form, $form_state);
// Just test if the #error_no_message property is TRUE. FormErrorHandlerTest
// tests if the property actually hides the error message.
$this->assertArraySubset(['#error_no_message' => TRUE], $form['test']);
}
}
......@@ -140,12 +140,9 @@ public function testSetElementErrorsFromFormState() {
}
/**
* Test that Quick Edit forms show non-inline errors.
*
* @covers ::handleFormErrors
* @covers ::displayErrorMessages
* Tests that opting out of Inline Form Errors works.
*/
public function testDisplayErrorMessagesNotInlineQuickEdit() {
public function testDisplayErrorMessagesNotInline() {
$form_error_handler = $this->getMockBuilder(FormErrorHandler::class)
->setConstructorArgs([$this->getStringTranslationStub(), $this->getMock(LinkGeneratorInterface::class), $this->getMock(RendererInterface::class)])
->setMethods(['drupalSetMessage'])
......@@ -157,7 +154,7 @@ public function testDisplayErrorMessagesNotInlineQuickEdit() {
$form = [
'#parents' => [],
'#form_id' => 'quickedit_field_form',
'#disable_inline_form_errors' => TRUE,
'#array_parents' => [],
];
$form['test'] = [
......@@ -165,7 +162,7 @@ public function testDisplayErrorMessagesNotInlineQuickEdit() {
'#title' => 'Test',
'#parents' => ['test'],
'#id' => 'edit-test',
'#array_parents' => ['test']
'#array_parents' => ['test'],
];
$form_state = new FormState();
$form_state->setErrorByName('test', 'invalid');
......
......@@ -116,6 +116,10 @@ public function buildForm(array $form, FormStateInterface $form_state, EntityInt
'#attributes' => ['class' => ['quickedit-form-submit']],
];
// Use the non-inline form error display for Quick Edit forms, because in
// this case the errors are already near the form element.
$form['#disable_inline_form_errors'] = TRUE;
// Simplify it for optimal in-place use.
$this->simplify($form, $form_state);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment