来自自定义字段IITEMLIST :: GetConstraints()的错误,每个属性旁边显示 -- entities 领域 drupal 相关 的问题

Errors from custom FieldItemList::getConstraints() displayed next to every single property


2
vote

问题

中文

摘要

默认情况下,根据自定义字段类型上的约束设置的错误。

我们可以在窗口小部件上使用 ::errorElement() 方法来放置来自 ::getConstraints() 方法的错误项目。 但是,来自 ::getConstraints() 在自定义字段中列表的错误不会通过 ::errorElement() 。我们如何合理地放置它们?

详细信息

我的原始问题是非常复杂的。我已经彻底简化了它,以展示什么是必不可少的。我们从一个非常简单的自定义字段类型开始,具有2个数字。

  class YearRangeType extends FieldItemBase {   public static function propertyDefinitions($field_definition) {     $properties['start'] = DataDefinition::create('integer');     $properties['end'] = DataDefinition::create('integer');     return $properties;   }    public static function schema($field_definition) {     $schema = ['columns' => [       'start' => ['type' => 'int',],       'end' => ['type' => 'int',],     ],];     return $schema;   }    public function isEmpty() {     $start = $this->get('start')->getValue();     $end = $this->get('end')->getValue();     return !($start || $end);   } }   

我们为其定义自定义 FieldItemList ,用于添加简单验证:检查至少2个项目是否存在。

  class YearRangeItemList extends FieldItemList {   public function getConstraints() {     $constraints = parent::getConstraints();     $constraints[] = $this->getTypedDataManager()       ->getValidationConstraintManager()       ->create('Count', [         'min' => 2       ]);     return $constraints;   } }   

当我尝试只保存一个项目时,该字段将如下所示:

错误出现在每个属性旁边。

如果错误是由 YearRangeType::getConstraints(), we could use the 窗小部件的错误()的方法,以放置它们。

但是,Drupal Core Class WidgetBase 故意不会通过项目列表设置的错误 998876610 ,请参阅 Drupal Core代码版本(版本8.8.1版) )。

我们应该怎么把它们放置?

英文原文

Summary

Errors set by constraints on custom field types appear next to every single property by default.

We can use the ::errorElement() method on the widget to place errors that come from the ::getConstraints() method of the field item.

However, errors that come from ::getConstraints() in a custom field item list will not go through ::errorElement(). How can we reasonably place them?

Details

My original problem ist very complicated. I've drastically simplified it to show only what's essential. We start with a very simple custom field type with 2 number properties.

class YearRangeType extends FieldItemBase {   public static function propertyDefinitions($field_definition) {     $properties['start'] = DataDefinition::create('integer');     $properties['end'] = DataDefinition::create('integer');     return $properties;   }    public static function schema($field_definition) {     $schema = ['columns' => [       'start' => ['type' => 'int',],       'end' => ['type' => 'int',],     ],];     return $schema;   }    public function isEmpty() {     $start = $this->get('start')->getValue();     $end = $this->get('end')->getValue();     return !($start || $end);   } } 

We define a custom FieldItemList for it that adds a simple validation: checking if at least 2 items are present.

class YearRangeItemList extends FieldItemList {   public function getConstraints() {     $constraints = parent::getConstraints();     $constraints[] = $this->getTypedDataManager()       ->getValidationConstraintManager()       ->create('Count', [         'min' => 2       ]);     return $constraints;   } } 

When I try to save only one item, the field will look like this:

Errors appear next to every single property.

If the errors would result from YearRangeType::getConstraints(), we could use theerrorElement()` method of the widget to place them.

However, the Drupal core class WidgetBase does deliberately not pass errors set by the item list to errorElement(), see these lines in the Drupal core code (version 8.8.1).

How else should we place them?

  

回答列表

0
 
vote
vote
最佳答案
 

我们可以在窗口小部件类中放置三种修改的错误。

首先,我们添加空表单元素 non_field_errors 我们可以将错误附加到。

  class YearRangeWidget extends WidgetBase {     ...     public function form($items, &$form, $form_state, $get_delta = NULL) {         $formElement = parent::form($items, $form, $form_state, $get_delta);         $formElement['non_field_errors'] = ['#type' => 'item'];         return $formElement;     }     ... }   

第二,在 flagErrors 方法中,我们收集了 not 属于任何属性的所有错误,并调用单独的方法来处理它们。

  class YearRangeWidget extends WidgetBase {     ...     public function flagErrors($items, $violations, $form, $form_state) {         $listViolations = [];         foreach ($violations as $key => $violation) {             if ($violation->getPropertyPath() === '') {                 $listViolations[] = $violation;                 $violations->remove($key);             }         }         parent::flagErrors($items, $violations, $form, $form_state);         $this->flagNonFieldErrors($items, $listViolations, $form, $form_state);     }     ... }   

第三,我们定义了处理分隔错误的方法。

  class YearRangeWidget extends WidgetBase {     ...     public function flagNonFieldErrors($items, $violations, $form, $form_state) {         $field = $items->getName();         foreach ($violations as $violation) {             $form_state->setError(                 $form[$field]['non_field_errors'],                 $violation->getMessage()             );         }     }     ... }   
 

We can place the errors with three modifications in the widget class.

First, we add the empty form element non_field_errors we can attach the errors to.

class YearRangeWidget extends WidgetBase {     ...     public function form($items, &$form, $form_state, $get_delta = NULL) {         $formElement = parent::form($items, $form, $form_state, $get_delta);         $formElement['non_field_errors'] = ['#type' => 'item'];         return $formElement;     }     ... } 

Second, in the flagErrors method, we collect all errors that do not belong to any property and call a separate method to treat them.

class YearRangeWidget extends WidgetBase {     ...     public function flagErrors($items, $violations, $form, $form_state) {         $listViolations = [];         foreach ($violations as $key => $violation) {             if ($violation->getPropertyPath() === '') {                 $listViolations[] = $violation;                 $violations->remove($key);             }         }         parent::flagErrors($items, $violations, $form, $form_state);         $this->flagNonFieldErrors($items, $listViolations, $form, $form_state);     }     ... } 

Third, we define the method treating the separated errors.

class YearRangeWidget extends WidgetBase {     ...     public function flagNonFieldErrors($items, $violations, $form, $form_state) {         $field = $items->getName();         foreach ($violations as $violation) {             $form_state->setError(                 $form[$field]['non_field_errors'],                 $violation->getMessage()             );         }     }     ... } 
 
 

相关问题

0  如何从Ajax表单中保存实体  ( How to save entity from a ajax form ) 
我正在运行drupal 8.8.x 问题 在通过AJAX提交表单时,未保存实体。示例: 构建形式 public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity = NULL) ...

0  Hook_Node_Presave期间如何重新排序实体引用版本字段?  ( How do you reorder an entity reference revisions field during hook node presave ) 
我正在尝试根据节点保存的文本字段重新排序一些段落,因此作者不需要手动维护字母顺序,但是当我保存节点时,所有值都丢失。我尝试匹配$ node-> get('field_paragraphs') - > getValue(),但这似乎没有工作。 function mymodule_node_presave...

1  大量的实体修订清洁导致连接堕胎  ( Large amount of entity revision cleaning leads to connection abortion ) 
我正在尝试通过DRUSH命令从具有修订功能的每个实体类型中删除修订。 实体的数量很多:10K节点约为2K段落。 在localhost上一切都很好。 但在云中,Drush_print($ log)成功运行,出现以下错误: [warning] PDO::beginTransaction(): MySQL serv...

1  在Cron运行期间将段落字段设置为null时出错  ( Error while set a paragraph field to null during cron run ) 
我正在使用drupal 8,我已经实现了 hook_cron ,将节点字段设置为null。这是我的代码: if ($lesson->field_lesson_ended_at->value < $current_time && $session_id && count($paragraphs) > 0) { ...

0  在这个实体上迁移可以将如何激发什么样的hook_entity?  ( What kind of hook entity can be trigerred by a migration on this entity ) 
我有一个自定义内容实体,我可以使用表单从CSV运行专用迁移。 该表单用于 上传CSV文件 启动迁移 表单的提交部分: $fileId = $form_state->getValue('file_to_import')[0]; $file = file_load($fileId); $uri = $...

1  EntityQuery不会返回值  ( Entityquery does not return values ) 
我正在尝试使用"Entity.Query" 服务获取一些实体。 我在做什么: 在我的模块(文件"mymodule.module" )我执行: function mymodule_preprocess_page(&$variables) { $query = Drupal::entityQuery('node'...

0  配置导入错误  ( Configuration import error ) 
我在本地系统中有drupal8。我想将我的生产环境配置导入我当地的。所以我正在运行 醉汉cim -y 我收到以下错误。 Unexpected error during import with operation update for core.entity_view_display.paragraph.card...

1  更新由hook_schema()定义的字段属性  ( Update field properties defined by hook schema ) 
我可能有点困惑文档。 在hook_schema()中有一些属性定义的自定义字段: /** * Some field type. * * @FieldType( * id = "field_selector", * label = @Translation("Selector"), * de...

-2  如何在实体引用自定义表单中使用Ajax在Drupal 8中显示没有实体错误?  ( How to use ajax in entity reference custom form to display no entity error in dr ) 
我在称为下面的名为项目的实体自动完成上创建了自定义表单, $form['items'] = array( '#title' => $this->t('Items'), '#type' => 'entity_autocomplete', '#target_type' => 'node', '...

0  尽早停止Hook_entity_Access?  ( Stop hook entity access early ) 
我们利用权限限制对各种内容的访问。但是,我们正在达到一些性能问题,因此我正在尝试添加一个允许/拒绝在某些条件下访问节点的补丁。 PBT通过Hook_entity_Access实现其访问控制。 但是,当用户命中节点并允许/拒绝访问它时,Hook_entity_Access继续运行其对页面上存在的每个其他实体的检查(这...

0  匿名用户的entityQuery  ( Entityquery for anonymous user ) 
在我的应用程序中,我有一个页面,它显示与视图相关的节点的视图和几个字段;当授权用户第一次访问页面时,将创建此节点。当节点发布时,可以通过匿名用户查看页面。 因此,当访问页面时,我有以下可能性: 授权用户和节点不存在:创建节点,然后在编辑模式下显示页面。 授权用户和节点存在:在编辑模式下显示页面。 匿名或未授权的用户...

1  将CSS类添加到实体参考(分类类型)作为节点中的字段呈现  ( Add css class to entity reference taxonomy type rendered as a field in a node ) 
这是我关于论坛的第一个问题。我目前正在开发一个网站(Drupal 8.8.1)。我正在在服务器上的子目录中开发它,而不是使用疏浚,服务器属于一个大型学术机构,他们不让我访问设置localhost。我对HTML和CSS有很好的理解,但只有PHP的基础知识。 我有一个非常具体的主题问题我需要一些帮助。我有一个分类词汇(作...

0  访问不工作的节点ID的内容.Theme文件  ( Accessing contents of a node id not working in theme file ) 
我有一个具有特定ID的页面(节点)。 在首页上,我想提取一个名为field_image1和field_link1的字段。 要做到我将以下内容添加到我的Themename.theme: function themename_preprocess_page(&$variables) { $variables...

0  通过Drupal 8中的主题文件访问内容的字段  ( Accessing the fields of a content via theme file in drupal 8 ) 
我有一个名为vanilla spice的内容类型,它有各种字段。 之后,我继续创建相关内容。 如何在我的主页中显示该内容类型的部分? 在我的主题中.module我做了以下内容: function amarula_preprocess_page(&$variables) { $nid = 61; $...

1  在更新挂钩中添加基本字段定义 - 它不会出现  ( Adding a base field definition in an update hook its not appearing ) 
我想将另一个基本字段添加到Drupal实体。它曾经是可以改变实体定义的代码,然后通过Drupal控制台更新它。但现在它必须在更新钩子中完成。 我已添加以下更新挂钩,完成 drush updb ,并且进程完成了没有错误。然后我做了 drush cr 清除缓存,然后打开有问题的实体的编辑表单,并给它一个硬刷新。但新领域没...

1  如何在自定义实体上显示基本字段的日期和时间选择器  ( How to display date and time picker for base field on custom entity ) 
我在使用"dateTime_default" 的"DateTime_Default" 中为"DateTime_Default" 进行了基本字段,用于表单显示。它只是仅显示日期选择器,没有时间组件,而我希望它看起来像这样: 如果我在GUI中创建一个字段,我可以在"仅限日期" 或"日期和时间" 之间进行选择。 (上...

0  显示与术语参考字段相关的标记的节点列表的视图  ( View showing a list of tagged nodes related to term reference field ) 
drupal 7 分类学词汇=公司活动(活动1,活动2,活动3 ......)。这个词汇有一个OG组字段。 内容类型1 =具有实体的公司(术语)参考字段,显示活动词汇表的列表。窗口小部件是"单选按钮框" 和公司的管理员,在创建内容期间,可能标记并保存所执行的相应活动。此内容类型具有OG组字段。 示例:1 - &...

0  在Drupal 8 BaseFieldDefinition中设置JSON字符串的显示选项:  ( Set display options for a json string in drupal 8 basefielddefinition ) 
我有一个字段,它将JSON字符串存储在数据库中的键和值。我希望从我的字段定义显示选项格式化此输出,以将JSON字符串输出为列表。是否有可能通过这种方法实现这一方法? $fields['charges'] = BaseFieldDefinition::create('string') ->setLabe...

-3  对于每个,将元素的标题设置为某些字符串  ( For each set elements title to some string ) 
嗨,我已经做了一个自定义模块来改变地址模块表单。它适用于一个字段,但是我试图为每个循环递归调用它,以便在那里的许多元素中使用A. 我的当前代码如下: function address_custom_address($element, $form_state) { $element[0]['address']...

0  如何重命名现有内容实体类型的字段?  ( How do i rename a field for an existing content entity type ) 
我创建了一种内容类型,我用它。 /** * @ContentEntityType( * id = "program_permission", * label = @Translation("Program permissions storage"), * base_table = "progr...




© 2021 it.wenda123.org All Rights Reserved. 问答之家 版权所有


Licensed under cc by-sa 3.0 with attribution required.