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

标签 angular validation tags angular7 ngx-chips

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

我怎样才能确保:

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

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

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...但这没有用

最佳答案

最终,此控件的笨拙实现使事情变得困难。如果它是一个包含当前输入和标签数组的模型的 ControlValueAccessor,找到解决方案会简单得多。

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

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

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

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

  • 为了进行验证,我必须获得对芯片的 TagInputComponent 的引用并调用 setInputValue(),传递已设置的值。相信我,在我偶然发现这种副作用之前,我尝试了上千种变体。尝试在您的组件上的 FormControl 实例或 TagInputComponent 中的各种 Form 和 FormControl 实例上调用 updateValueAndValidty() 从未完全奏效。
  • 为了防止添加(并且不清除输入),我必须返回一个可从 throwError() 观察到的错误。不幸的是,订阅在内部设置的方式是 TagInput 组件仅在其订阅回调函数上调用 catchError(),而不是在源可观察对象上。所以错误会显示在控制台中。再次 - 我尝试了很多不同的方法来解决它。

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);
}

关于angular - 添加和不清除的验证器(ngx-chips,angular),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54877393/

相关文章:

在 Tomcat 中刷新后出现 Angular 404 错误

Angular : An unhandled exception occurred: Cannot find module 'webpack/lib/ParserHelpers'

angular - 从 Angular 4.4.0 迁移到 Angular 5.2.0 导致服务器端渲染出错

Jquery 对话框和带有 IValidatableObject mvc3 的部分 View

php - 如何使用来自多个表的标签实现标签系统

html - float 在 img 标签上是可以的,但不适用于图形标签

javascript - ionic 4中的(按键)事件未触发

jquery - 将 qTip 与 MVC3 和 jQuery 验证集成 (errorPlacement)

c - 在 C 中读入一个正数

mysql从一个表中选择一个表,并从另一个表中获取concat结果