Angular 使用异步验证和Ngrx存储的反应式表单验证

Angular 使用异步验证和Ngrx存储的反应式表单验证,angular,rxjs,observable,ngrx,angular2-form-validation,Angular,Rxjs,Observable,Ngrx,Angular2 Form Validation,我正在开发一个Angular 8应用程序。我想使用NgRx存储显示表单错误,并使用自定义异步验证器显示反应式表单 login.component.ts @组件({ 选择器:“身份验证登录”, templateUrl:'./login.component.html', 样式URL:['./login.component.scss'], }) 导出类LoginComponent实现OnInit{ 公共transitionController:transitionController=新transit

我正在开发一个Angular 8应用程序。我想使用NgRx存储显示表单错误,并使用自定义异步验证器显示反应式表单

login.component.ts

@组件({
选择器:“身份验证登录”,
templateUrl:'./login.component.html',
样式URL:['./login.component.scss'],
})
导出类LoginComponent实现OnInit{
公共transitionController:transitionController=新transitionController(
是的,
);
公共形式:FormGroup;
公共页面状态$:可见;
public formSubmitted:boolean=false;
建造师(
private _formBuilder:formBuilder,
私人商店:商店,
) {
this.pageState$=this.\u store.select(selectLoginPagentate)作为可观察项<
伊洛金状态
>;
这个;
}
恩戈尼尼特(){
这个;
}
公共onFormSubmit(){
this.formSubmitted=true;
if(此.form.invalid){
返回;
}
this._store.dispatch(Login(this.form.value));
}
私人(buildForm){
this.form=this.\u formBuilder.group({
电子邮件:此。\u formBuilder.control(
无效的
[Validators.required,Validators.email],
[这个.测试.绑定(这个)],
),
密码:this.\u formBuilder.control(null,Validators.required),
});
}
专用测试(控件:AbstractControl){
返回此。\u store.select(选择LoginErrorMessage).pipe(
轻触(()=>console.log('executing'),
映射(值=>({
傅:是的
})),
);
}
私人_animatePage(){
此参数为.transitionController.animate(
新转换(EAnimationType.FadeUp,500,TransitionDirection.In),
);
}
}
登录页面.effects.ts

@Injectable()
导出类登录效果{
建造师(
私有_actions$:操作,
私有身份验证服务:身份验证服务,
专用路由器:路由器,
私人(u modalService):SuiModalService,,
私人商店:商店,
) {}
登录$=createEffect(()=>{
返回此.\u动作$.pipe(
类型(AuthActions.Login),
点击(()=>this.\u store.dispatch(ShowPageLoader()),
switchMap((凭证:iLogicCredentials)=>
此.\u authService.login(凭据).pipe(
map((response:ILoginResponse)=>authoctions.loginsAccess(response)),
catchError((响应:HttpErrorResponse)=>{
让validationErrors:validationErrors;
开关(响应状态){
案例HttpStatusCode.BAD_请求:
验证错误={
错误:{
validationErrors:response.error,
一般错误:
“哎呀!我们在您提供的详细信息中发现了一些错误。”,
},
};
打破
未找到案例HttpStatusCode.NOT\u:
验证错误={
错误:{generalError:'电子邮件或密码不正确。'},
};
打破
}
返回(AuthActions.LoginFailure(validationErrors));
}),
完成(()=>此._store.dispatch(HidePageLoader()),
),
),
);
});
LoginSAccess$=createEffect(
() => {
返回此.\u动作$.pipe(
类型(AuthActions.loginsAccess),
点击(()=>{
这是.\u modalService.open(
新的ModalComponent(未定义{
标题:“登录成功”,
imageSrc:'assets/images/modal/login successful.png',
}),
);
这个._router.navigateByUrl('/home');
}),
);
},
{调度:false},
);
}
这里的主要问题是在我的
测试
方法中。我希望在error字段上设置
{foo:true}
,但它永远不会发生。我在谷歌上搜索了很多次,找到了一个解决方案,就是在
管道()中添加
first()
方法,这样我的可观察性就完成了。它奏效了,但只是第一次。另外,提交表单时从未调用异步验证程序

我在internet上找到的所有示例都使用Http调用。我知道当请求完成时,它完成了可观察的操作,但在我的情况下,Http调用正在我的
登录页面.effects.ts中处理


有没有更好的办法?或者我需要一些我不熟悉的RxJs操作符吗?

您的
test()
函数中的
map
RxJs操作符不会返回您认为它是什么,因为
foo
被解释为标签,而不是您想要的对象文本中的键。有关更多说明,请参阅

有两种方法可以获得正确的语法

1.

map(值=>{
返回{foo:true};
}),
2.

map(值=>({foo:true}),

不要返回
这个。_store.select()
,尝试挂接到
操作
流监听多个操作完成事件
AuthActions.LoginFailure
AuthActions.loginsAccess

this.actions$.pipe(
        ofType(AuthActions.LoginFailure, AuthActions.LoginSuccess),
        switchMap(x => {
            if (x.type == AuthActions.LoginFailure)
                return this._store.pipe(
                    select(selectLoginErrorMessage),
                    map(msg => ({ foo: true })),
                    take(1)
                );
            return true;
        })
    )
store。选择
立即激发,不等待效果消失

现在回答另一个问题-

提交表单时从未调用异步验证程序


验证是在控件级别(
电子邮件
)上配置的,因此它不会被隐式触发。理想情况下,如果任何控件验证中存在错误,则不应允许提交表单。

我想说这是一个非常基本的错误。首先需要了解管道()之间的区别和订阅()

以下是一个有帮助的链接:

基本上,您的代码的问题是您正在observable上管道化操作,这意味着您的操作将只执行一次,并且它不会监视更改

你需要
this.error$ = this.store.select(selectLoadingErrors);
this.error$.subscribe(data=>{
//do your code here

});