我有一个验证指令,用于检查客户端密钥是否唯一。在检查网络流量并看到它正在为每次按键调用时,一切似乎都按预期工作。
import { Directive, forwardRef, ReflectiveInjector } from '@angular/core';
import { AbstractControl } from '@angular/common';
import { FormControl, NG_VALIDATORS } from '@angular/forms';
import {Observable} from 'rxjs/Rx';
import {DomainService} from '../services/domain.service';
interface IRefIdValidator {
}
function validateRefIdFactory(domainService : DomainService) {
return (control: AbstractControl): Observable<IRefIdValidator> => {
// get the domain Id and Ref Id key
let domainId: number = +control.root.find('domainId').value;
let clientId: number = +control.root.find('clientId').value;
let key: string = control.value;
// Return an observable with null if the
// reference id check comes back successful
return new Observable((obs: any) => {
control
.valueChanges
.debounceTime(500)
.distinctUntilChanged()
.flatMap(value => domainService.checkDomainClientKey(domainId, clientId, key))
.subscribe(
data => {
obs.next(null);
obs.complete();
},
error => {
obs.next({ refId: true });
obs.complete();
}
);
});
};
}
@Directive({
selector: '[validateRefId][formControlName],[validateRefId][ngModel],[validateRefId][formControl]',
providers: [
DomainService,
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => RefIdValidatorDirective), multi: true }
]
})
export class RefIdValidatorDirective {
validator: Function;
constructor(
private domainService: DomainService
) {
console.log('RefIdValidatorDirective created');
this.validator = validateRefIdFactory(this.domainService);
}
validate(c: AbstractControl) {
return this.validator(c);
}
}
我在模型驱动的形式中使用此验证指令:
this.domainForm = this.fb.group({
clientKey: ['', Validators.required, new RefIdValidatorDirective(this.domainService).validator]
});
正如您所看到的,这也是无效的,因为我将domainService从父组件传递给验证指令,但是,我一直无法弄清楚如何以任何其他方式将服务注入此指令
这是我的网络跟踪的样子,即使我正在快速打字:
24?key=Test
24?key=TestA
24?key=TestAB
24?key=TestABC
对此有任何帮助表示赞赏。
答案 0 :(得分:1)
您的代码存在问题:您没有返回Observable
,而是返回Subscription
,因为您正在订阅并返回。
要做到这一点,最好创建s Subject
去抖动每次击键。这是一个很好的做法,你可以适应你的需求。每次击键都会调用onSearch
方法:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
@Component({...})
export class ExampleComponent implements OnInit, OnDestroy {
private searchTermStream = new Subject<string>();
private searchSubscription: Subscription;
ngOnInit() {
this.searchSubscription = this.createInputSubscriber();
}
ngOnDestroy() {
this.searchTermStream.complete();
}
onSearch(query: string): void {
this.searchTermStream.next(query);
}
private createInputSubscriber(): Subscription {
return this.searchTermStream
.distinctUntilChanged()
.debounceTime(500)
.subscribe((query: string) => console.log(query));
}
}
这里我们还在组件被销毁时清除ngOnDestroy
方法中的内存。