Angular 2+:具有反应形式的自定义异步验证器

时间:2020-09-26 18:58:56

标签: angular customvalidator reactive-forms

我正在尝试从模板驱动切换为反应形式。我在添加异步验证器的过程中遇到了麻烦,因为它以模板驱动的形式在输入元素中设置了set属性,现在,当尝试从代码进行设置时,总是会出现一个奇怪的错误“ TypeError:undefined不是一个对象(评估'this.http' )“:

@Component({
    selector: 'app-new-user',
    templateUrl: './new-user.component.html',
    styleUrls: ['./new-user.component.css']
})
export class NewUserComponent implements OnInit, OnDestroy {
    isPosting: boolean = false;
    storeSub: Subscription;

    newUserForm: FormGroup;

    constructor(
        private userService: UsersService,
        private http: HttpClient,
        private store: Store<fromApp.AppState>
    ) {

    }

    ngOnInit() {
        this.storeSub = this.store.select('users')
            .subscribe(state => {
                    this.isPosting = state.isPostingNewUser;
                }
            );
        this.newUserForm = new FormGroup({
            'name': new FormControl(null, [
                Validators.required,
                Validators.maxLength(30),
                Validators.minLength(3)
            ]),
            'surname': new FormControl(null, [
                Validators.required,
                Validators.maxLength(50),
                Validators.minLength(3)
            ]),
            'email': new FormControl(null, [
                    Validators.required,
                    Validators.email
                ],
                this.checkEmailAvailability
            ),
            'phone': new FormControl(null, [
                    Validators.required,
                    Validators.maxLength(9),
                    Validators.pattern('[5-8][0-9]{8}')
                ]
            )
        });

    }

    ngOnDestroy() {
        this.storeSub.unsubscribe();
    }

    onSubmit(): void {
        const userWriteModel = new UserWriteModel(
            this.newUserForm.get('name').value,
            this.newUserForm.get('surname').value,
            this.newUserForm.get('email').value,
            this.newUserForm.get('phone').value
        );
        this.store.dispatch(new UserActions.AddUser(userWriteModel));
    }

    checkEmailAvailability(control: FormControl): Observable<{ emailForbidden: boolean } | null> {
        const emailToCheck = control.value;
        if(!emailToCheck) {
            return of(null);
        }
        const queryParams = new HttpParams().set('email', emailToCheck);
        console.log(emailToCheck);
        return of(emailToCheck).pipe(
            debounceTime(400),
            switchMap(emailToCheck => {
                return this.http.get<{ email: string, available: boolean }>(ENDPOINT + '/email/available', {params: queryParams})
                    .pipe(
                        map(resp => {
                            if (resp.email === emailToCheck && resp.available === false) {
                                return {emailForbidden: !resp.available};
                            }
                            return null;
                        }), catchError(() => of(null)));
            })
        );
    }
}

验证结束时:

[Error] ERROR
TypeError: undefined is not an object (evaluating 'this.http')
(anonimowa funkcja) — new-user.component.ts:106
_next — switchMap.js:30
next — Subscriber.js:49
debouncedNext — debounceTime.js:40
_complete — debounceTime.js:31
complete — Subscriber.js:61
(anonimowa funkcja) — subscribeToArray.js:5
_trySubscribe — Observable.js:42
subscribe — Observable.js:28
subscribe — Observable.js:23
subscribe — Observable.js:23
(anonimowa funkcja) — forkJoin.js:37
_trySubscribe — Observable.js:42
subscribe — Observable.js:28
subscribe — Observable.js:23
_runAsyncValidator — forms.js:3032
updateValueAndValidity — forms.js:3005
setValue — forms.js:3386
updateControl — forms.js:2407
(anonimowa funkcja) — forms.js:2392
_handleInput — forms.js:242
executeListenerWithErrorHandling — core.js:14296
wrapListenerIn_markDirtyAndPreventDefault — core.js:14331
(anonimowa funkcja) — platform-browser.js:582
onInvokeTask — core.js:27137
runTask — zone-evergreen.js:167
invokeTask — zone-evergreen.js:480
invokeTask — zone-evergreen.js:1621
globalZoneAwareCallback — zone-evergreen.js:1647
dispatchEvent
_autoFillControlWithValueAndOptions
_autoFillControlWithValue
(anonimowa funkcja)
[native code]
    defaultErrorLogger (vendor.js:18351)
    handleError (vendor.js:18399)
    next (vendor.js:41970)
    (anonimowa funkcja) (vendor.js:38808)
    __tryOrUnsub (vendor.js:70827)
    next (vendor.js:70766)
    _next (vendor.js:70716)
    next (vendor.js:70693)
    next (vendor.js:70479)
    emit (vendor.js:38798)
    run (polyfills.js:136)
    onHandleError (vendor.js:41442)
    runTask (polyfills.js:183)
    invokeTask (polyfills.js:493)
    timer (polyfills.js:2565)```

1 个答案:

答案 0 :(得分:0)

您的验证器使用您的类成员,但是由于您将其作为引用传递,因此this的定义不正确。

尝试:

'email': new FormControl(null, [
                    Validators.required,
                    Validators.email
                ],
                this.checkEmailAvailability.bind(this)
            ),