【问题标题】:Angular 8 - Validator with AngularFireDatabase callAngular 8 - 带有 AngularFireDatabase 调用的验证器
【发布时间】:2020-05-01 18:26:14
【问题描述】:

我在构建调用 firebase 数据库的验证器时遇到问题。代码如下,我们来看看验证器。假设我在数据库中有数组 ['track1','track2']。当trackName 字段填充track1 值时,控制台返回a,这是它应该的。但我发现,existingTrack 错误没有出现。而不是这个错误,我在 FormGroup 中得到了下面提到的错误:

errors:
closed: false
destination: SafeSubscriber {closed: false, _parent: null, _parents: null, _subscriptions: null, syncErrorValue: null, …}
isStopped: false
syncErrorThrowable: true
syncErrorThrown: false
syncErrorValue: null
_parent: null
_parents: null
_subscriptions: [MapSubscriber]
__proto__: Object

我尝试在表单生成器中将validator 更改为asyncValidator,但在这样做之后,验证器完全停止工作。我认为订阅和管道词可能有问题,我不确定何时使用哪个。

组件代码:

constructor(public fb: FormBuilder, private dataService: DataService) {}

ngOnInit() {

this.form = this.fb.group({
          newTrack: this.fb.control(false, Validators.required),

          trackName: this.fb.control(''),
          trackLength: this.fb.control('', [Validators.pattern('^[0-9]{1,}.[0-9]{1,2}$')]),
          trackSelect: this.fb.control(''),

          time: this.fb.control('', [Validators.required, Validators.pattern('^[0-9]{1,}:[0-9]{2}$')]),
          date: this.fb.control('', [Validators.required])
      }, 
      {validator: this.tracksDataValidator.bind(this)});
}

    tracksDataValidator(group: FormGroup) {

            const newTrack = group.get('newTrack').value;
            const trackSelect = group.get('trackSelect').value;
            const trackName = group.get('trackName').value;
            const trackLength = group.get('trackLength').value;


            return this.dataService.isTrackTaken(trackName).subscribe((res: any[]) => {
                    if (newTrack === true) {
                        if (res.length > 0) {
                            console.log('a');
                            return {existingTrack: true};
                        }
                        if (trackName === '' || trackLength === '') {
                            return {newTrackNotFilled: true};
                        }
                    } else {
                        if (trackSelect === '') {
                            return {noTrackSelected: true};
                        } else {
                            return null;
                        }
                    }
                });
        }

数据服务

constructor(private db: AngularFireDatabase) {}

isTrackTaken(trackName: string) {
        return this.db.list('/tracks').valueChanges()
            .pipe(map(tracks => tracks.filter((track: Track) => track.name === trackName)));
    }

编辑:

我尝试以与 alligator.io 网站上完全相同的方式创建验证器,我将表单构建器更改为

this.form = this.fb.group({
          newTrack: this.fb.control(false, Validators.required),

          trackName: this.fb.control('', [Validators.required], this.trackDataValidator.bind(this)),
          trackLength: this.fb.control('', [Validators.pattern('^[0-9]{1,}.[0-9]{1,2}$')]),
          trackSelect: this.fb.control(''),

          time: this.fb.control('', [Validators.required, Validators.pattern('^[0-9]{1,}:[0-9]{2}$')]),
          date: this.fb.control('', [Validators.required])
      });

和验证者

trackDataValidator(control: FormControl) {
      return this.dataService.isTrackTaken(control.value).subscribe((res: any[]) => {
          return (res.length > 0) ? {existingTrack: true} : null;
      });
  }

DataService 代码相同。在trackName 字段中输入每个字母后,都会出现此错误:

ERROR Error: Expected validator to return Promise or Observable.
    at toObservable (forms.js:1466)
    at Array.map (<anonymous>)
    at FormControl.asyncValidator (forms.js:1446)
    at FormControl._runAsyncValidator (forms.js:4100)
    at FormControl.updateValueAndValidity (forms.js:4053)
    at FormControl.setValue (forms.js:4692)
    at updateControl (forms.js:3299)
    at DefaultValueAccessor.onChange (forms.js:3271)
    at DefaultValueAccessor._handleInput (forms.js:419)
    at Object.eval [as handleEvent] (NewTrainingComponent.html:14)

【问题讨论】:

    标签: angular firebase


    【解决方案1】:

    我建议阅读以下内容: https://alligator.io/angular/async-validators/

    基本上你需要返回一个 Observable 而不是订阅 Observable 的结果。

    让我知道这是否有效。

    此外,formcontrol 将在表单值更改时自行执行订阅:

    • 请注意 API 调用,如有必要,请使用以下选项:{updateOn: 'blur'} (FormControl('', {updateOn: 'blur'});)
    • Observable 需要完成订阅,因此请使用管道:first、last、take 或 takeUntil。

    【讨论】:

    • 我只是尝试以同样的方式做,结果在我的问题的末尾
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-18
    • 2021-12-09
    • 1970-01-01
    • 2021-02-03
    • 2020-07-20
    • 2014-12-07
    相关资源
    最近更新 更多