Problem/Motivation

In #2840085: deleting Paragraph in draft state causing js error we realize that when a paragraph with a number integer (required) field is removed from the node, it goes through the number widget errorElement function and breaks the ajax submit. I'm actually not really sure how to trigger this in core. But the steps for reproducing should be:
1. Create a node with a required multivalue integer field.
2. Add a value to the first element, add another element.
3. With no values in the new element, attempt to remove it. It should fail.

If we try with no required fields everything works as expected.

Proposed resolution

The return value of the errorElement function of the NumberWidget might be the problem cause it returns $element['value']; and the 'value' key won't be set if that is a multivalue field, maybe it just needs to return the $element ?

Remaining tasks

User interface changes

API changes

Data model changes

Comments

yongt9412 created an issue. See original summary.

johnchque’s picture

Status: Active » Needs review
StatusFileSize
new660 bytes

Actually this should work without breaking the functionality. Let's try, not sure how to test this.

cilefen’s picture

Issue tags: +Needs tests

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

lomo’s picture

Status: Needs review » Closed (cannot reproduce)

Seems like this issue has been resolved already; I've seen a number of issue tickets related to weirdness with the number field and similar, so I think one of those must have fixed the bug. That, or the "steps to reproduce" is missing something.

mpp’s picture

Status: Closed (cannot reproduce) » Needs work

Steps to reproduce:

1. create a number field (integer) on a paragraph

2. add a constraint:

class LimitConstraint extends Constraint {
  public $message = 'The limit is invalid.';
}

3. add a validator

class LimitConstraintValidator extends ConstraintValidator {

  public function validate($entity, Constraint $constraint) {
    $this->context->addViolation($constraint->message);
  }

}

4. apply the constraint to the field:

/**
 * Implements hook_entity_bundle_field_info_alter().
 */
function MODULE_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
  if ($entity_type->id() === 'paragraph' && $bundle === 'list' && !empty($fields['field_number'])) {
    $fields['field_number']->addConstraint('Limit', []);
  }
}

As soon as the violation is added, the following error will occur: Undefined index: value in NumberWidget.php on line 114

The patch in #2 fixes the issue.

pacproduct’s picture

StatusFileSize
new694 bytes

I am facing a very similar issue with a number field on a content type that also includes a Inline Entity Form (IEF) on another field.
When trying to cancel the addition of a node to the IEF, an AJAX call is made to the backend which triggers a form validation and the following Exception gets thrown: Error: Argument 1 passed to Drupal\\Core\\Form\\FormState::setError() must be of the type array, null given, called in /var/www/html/mysite/www/core/lib/Drupal/Core/Field/WidgetBase.php on line 439 in ...
(see https://www.drupal.org/node/2915505)

That is because the call to NumberWidget::errorElement() just before returns NULL as it tries returning $element['value'] which is undefined. It is defined in $element[0]['value'] but my understanding is that we're not really interested in the value but in the whole form element instead (so we can flag it as being in error).

Because of that I'm not sure the problem comes from IEF in the end: After reading what WidgetInterface::errorElement() is supposed to return (that is "The element on which the error should be flagged, or FALSE to completely ignore the violation (use with care!).") I'm not sure why NumberWidget::errorElement() tries returning a value.

The default implementation (WidgetBase::errorElement()) looks better suited as it simply returns the whole element (as suggested by yongt9412's patch).

My patch attached is similar to yongt9412's in the sense that it reverts the default behavior of WidgetBase::errorElement() but I achieved that by removing completely NumberWidget::errorElement() so it fallbacks to the parent implementation.

This does solve my issue apparently, I just hope it does not break anything else?

simon georges’s picture

Status: Needs work » Needs review
crzdev’s picture

Related issues: +#1785256: Widgets as Plugins

Patch seems work fine, thanks.
Tested both but "NumberWidget_errorElement-2840102-7.patch" maybe is more correctly due parent method is used.

That was introduced long time ago, more info: "Widgets as Plugins" https://www.drupal.org/node/1785256

idebr’s picture

amateescu’s picture

Status: Needs review » Closed (duplicate)
Issue tags: -Needs tests