【问题标题】:Angular Material: How to validate Autocomplete against suggested options?Angular Material:如何根据建议的选项验证自动完成功能?
【发布时间】:2019-01-23 02:23:00
【问题描述】:

我们有一个带有required 验证的自动完成输入。当用户通过输入查询(但未选择任何选项)搜索选项时,即使输入与任何建议的选项都不匹配,该输入也是有效的。

我想要实现的是不允许用户发布表单,除非选择了建议的选项之一。我如何做到这一点?

<mat-form-field>
   <input matInput placeholder="Pick one" aria-label="pick one" [matAutocomplete]="auto" [formControl]="form.controls['SELECTBOX_VALUE']">
      <mat-autocomplete #auto="matAutocomplete">
           <mat-option *ngFor="let option of myOptions | async" [value]="option.name"> <span>{{ option.name }}</span> </mat-option>
            </mat-autocomplete>
</mat-form-field>
<small *ngIf="!form.controls['SELECTBOX_VALUE'].valid && form.controls['SELECTBOX_DEGER'].touched" class="mat-text-warn">Please select.</small>

ngOnInit() {
    this.form = this.fb.group({
        ... some other fields
        SELECTBOX_VALUE: [null, Validators.required]
    });

我的自动编译过滤器代码非常简单:

this.form.get('SELECTBOX_VALUE').valueChanges
        .pipe(
            startWith(''),
            map(option => secenek ? this.doFilter(option) : this.options.slice())
        );

doFilter (name: string) {
    return this.myOptions.filter(option =>
        option.name.toLowerCase().indexOf(name.toLowerCase()) === 0);
}

【问题讨论】:

标签: angular angular-material angular-reactive-forms


【解决方案1】:

您可以在提交函数中添加字段的验证检查,

Submit() {
 if(this.form.valid) {
   // send to API
 } else {
   // show error
 }
}

【讨论】:

  • 我想在html中实现这个。你认为没有办法吗?
  • 可以禁用提交按钮,[disabled]="!form.valid"
  • 但我在原始问题中提到,表单始终有效,因为验证机制仅检查选择框的任何字符串值的要求。所以我不认为 [disabled]="!form.valid" 会起作用。
【解决方案2】:

对于那些可能需要类似方法的人。这是我的解决方案。我已经根据自己的需要构建了一个自定义验证规则。

SELECTBOX_VALUE: [
  null,
  Validators.compose([
    Validators.required,
    FormCustomValidators.valueSelected(this.myArray),
  ]),
];

export class FormCustomValidators {
  static valueSelected(myArray: any[]): ValidatorFn {
    return (c: AbstractControl): { [key: string]: boolean } | null => {
      let selectboxValue = c.value;
      let pickedOrNot = myArray.filter(
        (alias) => alias.name === selectboxValue
      );

      if (pickedOrNot.length > 0) {
        // everything's fine. return no error. therefore it's null.
        return null;
      } else {
        //there's no matching selectboxvalue selected. so return match error.
        return { match: true };
      }
    };
  }
}

【讨论】:

  • 谢谢,我使用你的方法稍作修改,因为我的值数组是后来从 Observable 初始化的。我的版本传入一个函数而不是数组,例如:static valueSelected&lt;T&gt;(exists: (value: T) =&gt; boolean): ValidatorFn ,条件变为if(exists(selectedboxValue)) {
【解决方案3】:

Angular Material Autocomplete 有两种情况可能需要根据所选选项列表进行验证:

  1. 字符串数组 - 建议的选项在字符串数组中定义
  2. 对象数组 - 建议的选项是在对象数组上定义的对象属性(在这种情况下,将使用 displayWith 输入。)

** Stackblitz Demo **

验证字符串数组中的选项

要针对字符串选项数组验证autocomplete,验证器可以接受选项数组并检查是否包含控制值。

function autocompleteStringValidator(validOptions: Array<string>): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } | null => {
    if (validOptions.indexOf(control.value) !== -1) {
      return null  /* valid option selected */
    }
    return { 'invalidAutocompleteString': { value: control.value } }
  }
}

验证器可以与Validators.required等其他内置验证器一起添加到FormControl

public autocompleteControl = new FormControl('', 
      { validators: [autocompleteStringValidator(this.options), Validators.required] })

验证对象数组中的选项

要针对一组对象选项验证 autocomplete,验证器可以利用以下事实:如果未选择有效的 Object 选项,则 control.value 将仅是 string

function autocompleteObjectValidator(): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } | null => {
    if (typeof control.value === 'string') {
      return { 'invalidAutocompleteObject': { value: control.value } }
    }
    return null  /* valid option selected */
  }
}

【讨论】:

    猜你喜欢
    • 2020-10-25
    • 2013-11-18
    • 2015-12-29
    • 2015-08-22
    • 1970-01-01
    • 2016-03-23
    • 2018-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多