如果用户输入的输入与列表中的项匹配,我想检查带有异步验证器的自动完成小部件。
如果用户输入的值与已过滤列表中的项匹配,则其有效,否则无效。
伪代码中的示例(状态/过滤将来自异步API):
states: ['Michigan', 'Minnesota', 'Mississippi']
user input 'mi':
filteredStates: ['Michigan', 'Minnesota', 'Mississippi'] -> invalid because 'mi' does not match excact any value
user input 'Michigan':
filteredStates: ['Michigan'] -> valid because we have an excact match
使用Async Validator是因为我想重用我正在使用的observable来对值的变化做出反应并根据我得到的值过滤掉项目。
使用过滤值进行观察:
this.stateCtrl = new FormControl('', [], this.stateExists());
this.filteredStates = this.stateCtrl.valueChanges
.startWith(null)
.map(name => this.filterStates(name));
异步验证器:
stateExists(states): AsyncValidatorFn {
return (control: AbstractControl): Observable<any> => {
if(!control.dirty || !control.value || control.value.length === 0) return Observable.of(null);
return this.filteredStates
.switchMap(states => Observable.from(states))
.filter(state => state === control.value)
.do(() => console.log('state matches value'))
.map(() => null)
}
}
Plnkr: http://plnkr.co/edit/vxkbS8Icg7crUGIyfAQK?p=preview (实际上我的价值观来自API)
我有两个问题:
我无法在验证器中传递可观察的过滤状态,因为此时它不存在。现在,每次验证器运行时,它都会获得一个新的observable,并且会在调用验证器时调用它。
如果值匹配,我的验证器会过滤掉,但我如何更改代码以映射对象,例如{notFound:true}如果我找不到值,如果找到值则为null?在我的例子中,它将永远不会被过滤掉。
答案 0 :(得分:1)
我认为您混淆了异步验证器和异步字段值:您的字段可能异步获取其值,但它并不代表验证器也应该是异步的。
验证程序并不关心值是来自异步HTTP调用还是来自键入字段的用户。当它执行其验证工作时,该值存在(它是&#34;同步&#34;如果你愿意的话)。
因此,您可以按如下方式简化代码:
// Attach a SYNCHRONOUS validator to the field.
this.stateCtrl = new FormControl('', this.stateExistsSync('California'));
// Declare the synchronous validator.
stateExistsSync(validState: string): ValidatorFn {
return (control: AbstractControl) => {
return control.value && control.value != validState ? { stateMismatch: true } : null;
};
}
Plunkr:http://plnkr.co/edit/1WSueXS1oBBmgfh5OCuN?p=preview
请注意,验证器接受validState
作为参数。
仅供参考,当验证本身触发异步操作时,使用异步验证器,例如,用于验证用户名是否已被使用的HTTP请求。