使用Observable from Service的Angular反应形式异步验证

时间:2019-10-01 14:18:40

标签: angular angular-reactive-forms

我正在Angular 8.3.4中做一个Web应用程序。我有一个使用“反应式表单”的表单,并且我想添加“异步验证”以确保输入的名称是唯一的。我已经阅读了很多示例,但是由于某些原因对我不起作用。

服务

export class BrandService {
  brands: Observable<BrandId[]>;
}

组件

export class CreateNewComponent {

  form: FormGroup;

  constructor(
    private formBuilder: FormBuilder,
    private brandService: BrandService
  ) {
    // Creates a form group
    this.form = this.formBuilder.group({
      name: ['', Validators.compose([
        Validators.required,
        Validators.minLength(6),
        CustomValidator.unique(this.brandService.brands)
      ])]
    });
  }
}

自定义验证器

export class CustomValidator {

  static unique(brands: Observable<BrandId[]>) {
    return (control: AbstractControl) => {

      const name = control.value.toLowerCase();

      return brands.pipe(
        map(items => items.filter(b => b.name.toLowerCase() === name)),
        map(items => items.length ? {unique: false} : null)
      );

    };
  }

}

我正在将服务的Observable从组件传递到CustomValidator。现在,该控件具有:status: "INVALID"

顺便问一下,我应该在unique方法中显式返回什么?

我的目标是知道该名称是否已经存在于Observable的数组中,以返回控制错误。

1 个答案:

答案 0 :(得分:0)

异步验证器应通过另一个数组(或单独)传递,例如

name: [
  '', 
  Validators.compose([ Validators.required, Validators.minLength(6)]), 
  () => CustomValidator.unique(this.brandService.brands)
]

还要注意,它在一个函数中,我早些时候发现的许多示例都使用in this article之类的bind,但我更喜欢使用一个函数。

------编辑------ 这是一个有效的例子

@Component({
  selector: 'app-new',
  templateUrl: './new.component.html',
  styleUrls: ['./new.component.css']
})
export class NewComponent {

  form: FormGroup;

  constructor(
    private formBuilder: FormBuilder,
    private brandService: BrandService,
  ) {
    const brand = new BrandId();
    brand.name = 'abcdef';

    this.brandService.brands = of([brand]);
    // Creates a form group
    this.form = this.formBuilder.group({
      name: ['', Validators.compose([
        Validators.required,
        Validators.minLength(6),
      ]),
        (control) => CustomValidator.unique(this.brandService.brands, control)]
    });
  }
}

export class CustomValidator {
  static unique(brands: Observable<BrandId[]>, control: AbstractControl) {
    const name = control.value.toLowerCase();

    return brands.pipe(
      map(items => items.filter(b => b.name.toLowerCase() === name)),
      map(items => items.length ? { unique: false } : null)
    );

  }
}
相关问题