添加和不清除验证器(ngx-chips,angular)

问题描述 投票:5回答:2

我正在使用ngx-chips将一组电子邮件作为标签添加到输入中。验证器确保每个标签看起来像电子邮件。

我怎样才能确保:

1)验证器仅在添加标签时触发(即,用户点击输入,空格或逗号)

2)如果在命中输入/ space /逗号时电子邮件无效,则该值仍然存在(即,它不会清除...以便用户可以修复它)

stackblitz在这里:https://stackblitz.com/edit/ngx-chips-example-2qdudc

以下是我的电子邮件验证员:

public validators = [ this.must_be_email ];
  public errorMessages = {
      'must_be_email': 'Please be sure to use a valid email format'
  };
  private must_be_email(control: FormControl) {        
      var EMAIL_REGEXP = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,3}$/i;
      if (control.value.length != "" && !EMAIL_REGEXP.test(control.value)) {
          return { "must_be_email": true };
      }
      return null;
  }

以下是标签:

<tag-input [(ngModel)]='emails' 
name="emails" 
#email="ngModel" 
[errorMessages]="errorMessages"
[validators]="validators" 
[editable]='true' 
(onTagEdited)="onTagEdited($event)" 
[separatorKeyCodes]="[32,188,186,13,9]"
[placeholder]="'Add email'" 
[secondaryPlaceholder]="'Enter email address(es)'" 
[clearOnBlur]="true" 
[addOnPaste]="true"
[addOnBlur]="true"
[pasteSplitPattern]="splitPattern" 
theme='bootstrap' 
required >
</tag-input>

对于2),我尝试在验证器中将“return null”更改为control.value ...但是这不起作用

angular validation tags angular7 ngx-chips
2个回答
2
投票

最终,这种控制的笨拙实现使事情变得困难。如果它是一个ControlValueAccessor,其模型包含当前输入和标签数组,那么找到解决方案将更加简单。

和@ AlesD的答案一样,我选择了一个利用onAdding的解决方案。他提出的一个问题是使用this的问题。为了解决这个问题,我在必要时使用bind()函数。

为了实现你想要的行为,我做了三件事:

  1. 修改验证器函数,以便在字段addFirstAttemptFailed为true时仅返回错误。这将阻止验证器执行。
  2. 添加回调给onAdding。它验证标记,如果验证失败,则将addFirstAttemptFailed设置为true并返回可观察的错误(我升级到rxjs 6)。抛出此错误会阻止添加标记。
  3. 成功添加项目后,addFirstAttemptFailed将重新设置为false,以便可以再次为下一个标记开始行为。

不幸的是,在onAdding期间调用的方法有一些装备。

  • 为了进行验证,我必须获得对chip的TagInputComponent的引用并调用setInputValue(),传递已经设置的值。相信我,在偶然发现这种副作用之前,我尝试了一千种变体。试图在组件上的FormControl实例上调用updateValueAndValidty(),或者在TagInputComponent中的Form和FormControl的各种实例上调用throwError()
  • 为了防止添加(并且没有输入被清除),我必须从catchError()返回一个可观察到的错误。不幸的是,内部设置订阅的方式是TagInput组件仅在其订阅回调函数上调用Relevant code,而不是在源可观察对象上调用@ViewChild('tagInput') tagInput: SourceTagInput; public validators = [ this.must_be_email.bind(this) ]; public errorMessages = { 'must_be_email': 'Please be sure to use a valid email format' }; public readonly onAddedFunc = this.beforeAdd.bind(this); private addFirstAttemptFailed = false; private must_be_email(control: FormControl) { if (this.addFirstAttemptFailed && !this.validateEmail(control.value)) { return { "must_be_email": true }; } return null; } private beforeAdd(tag: string) { if (!this.validateEmail(tag)) { if (!this.addFirstAttemptFailed) { this.addFirstAttemptFailed = true; this.tagInput.setInputValue(tag); } return throwError(this.errorMessages['must_be_email']); } this.addFirstAttemptFailed = false; return of(tag); } 。因此错误会显示在控制台中。再次 - 我尝试了一些不同的方法来解决它。

onAdding

GitHub source code of the tag-input-form component

1
投票

ngx-chips有一个事件onKeyDown,你可以用来做额外的检查。在事件处理程序内部,您可以检查组件是否有效,如果控件无效,则取消添加。然后文本将保留。对于Enter键,它无法工作,因为Enter键被编码为提交表单并始终清除文本。您可以在标签输入内部​​使用的public onAdding(tag): Observable<string> { if (!this.hasErrors()) { // this is tricky the this here is actually the ngx-chips tag-input component return of(tag); } else { return EMPTY; } } 中看到它。检查this方法。

以下是组件中onAdding处理程序的示例实现:

<tag-input ... [onAdding]="onAdding">

正如我在代码中的注释中已经提到的,因为事件处理程序是如何被调用的,函数内部的fork of your stackblitz实际上是ngx-chips标签输入组件而不是你通常期望的组件。

拥有此方法后,您只需将其绑定在模板中即可。

chip input component

我用这个实现创建了一个qazxswpoi。

如果这不起作用,您可能需要联系组件的作者以获取更多详细信息或使用其他组件。例如,Angular材料组件包含类似的qazxswpoi。

© www.soinside.com 2019 - 2024. All rights reserved.