简体   繁体   English

如何在使用 NgRX 管理 state 的项目中关闭模式

[英]How to close modals in project that uses NgRX to manage state

Is there any good solution when working with modals in a project where state is managed by NgRX?在 state 由 NgRX 管理的项目中使用模态时有什么好的解决方案吗?

The problem I have the following:我有以下问题:

  • User clicks on button to create a new item.用户单击按钮以创建新项目。
  • Modal window opens.模态 window 打开。
  • User fills out the form and clicks on Submit.用户填写表格并点击提交。
  • Dispatch an action, effects fires up and creates an item by sending HTTP request.通过发送 HTTP 请求,调度一个动作,触发效果并创建一个项目。
  • Now I need to close modal on success.现在我需要在成功时关闭模式。 How do I know when to close it either inside modal component or inside component that opened this modal?我如何知道何时在模态组件或打开此模态的组件内部关闭它?

One of the solutions I see right now is to return multiple actions from the effect, one that adds created item to the store, second one to close the modal.我现在看到的解决方案之一是从效果中返回多个动作,一个将创建的项目添加到商店,第二个是关闭模式。 For this I should include some modal identifier in "Create" action to identify which modal to close after "Create$" effect completes, but this will make effect more complicated.为此,我应该在“创建”操作中包含一些模式标识符,以识别在“创建 $”效果完成后关闭哪个模式,但这会使效果更加复杂。

I can't believe there is no ready solution to this problem.我不敢相信这个问题没有现成的解决方案。

I use ngx-bootstrap for modals.我将 ngx-bootstrap 用于模态。

UPDATE: Seems like to make this work I need to store (state + reducer + effects + actions) open/closed status for each modal available in the application.更新:似乎要完成这项工作,我需要为应用程序中可用的每个模式存储(状态+减速器+效果+动作)打开/关闭状态。 But anyway, no existing solution?但无论如何,没有现成的解决方案?

I like to use an effect to handle the whole dialog flow, from opening the dialog to saving the entity and closing the dialog afterwards.我喜欢使用效果来处理整个对话框流程,从打开对话框到保存实体,然后再关闭对话框。

@Effect()
openDialog = this.actions.pipe(
  ofType(LoginActionTypes.OpenLoginDialog),
  exhaustMap(_ => {
    let dialogRef = this.dialog.open(LoginDialog);
    return dialogRef.afterClosed();
  }),
  map((result: any) => {
    if (result === undefined) {
      return new CloseDialog();
    }
    return new LoginDialogSuccess(result);
  }),
);

See Start using ngrx/effects for this for more info.有关详细信息,请参阅开始使用 ngrx/effects

There is a very common pattern that many developers use an which works create.许多开发人员使用一种非常常见的模式来创建作品。 Define three actions for your request: submitForm , submitFormSuccess and submitFormFailed .为您的请求定义三个操作: submitFormsubmitFormSuccesssubmitFormFailed

Now you have to think about your state.现在您必须考虑您的 state。 Does anything change when the data arrives before the Modal closes?当数据在模态关闭之前到达时有什么变化吗? If so create another action, eg closeModal .如果是这样,请创建另一个动作,例如closeModal Then the success action triggers the close modal action.然后成功动作触发关闭模式动作。 In this pattern usually someone wants to store the success response somewhere in your store.在这种模式下,通常有人希望将成功响应存储在您商店的某个位置。

Then you have got three effects for it.那么你就得到了三个效果。 Of course you can create an effect that listens directly to the success action, if you do not want to create another closeModal action.当然,如果您不想创建另一个closeModal动作,您可以创建一个直接监听成功动作的效果。 You can register multiple effects on one "ofType" action.您可以在一个“ofType”动作上注册多个效果。

createEffect(() => this.actions$.pipe(
  ofType(submitForm),
  switchMap((value) => this.myService.submit(value).pipe(
    map(response => submitFormSuccess()),
    catchError(error => of(error))
  ))
));

createEffect(() => this.actions$.pipe(
  ofType(submitFormSuccess),
  map(() => closeModal)
));

createEffect(() => this.actions$.pipe(
  ofType(closeModal),
  tap(() => this.modalReference.close())
), { dispatch: false });

You have to inject NgbActiveModal in the constructor of the component and call the method close(REASON) on it.您必须在组件的构造函数中注入NgbActiveModal并在其上调用close(REASON)方法。 So in the component you do:所以在你做的组件中:

import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';

export class ResetConfirmationComponent {

    constructor(
        public activeModal: NgbActiveModal
    ) { }
}

And in the template for that component:在该组件的模板中:

<button type="button" class="btn btn-primary btn-default"
    (click)="activeModal.close('Reason for being closed ...')">
    Submit
</button>
<button type="button" 
    (click)="activeModal.dismiss('closed')">
    <span aria-hidden="true">&times;</span>
</button>

I don't know how you could close the dialog "on success".我不知道您如何“成功”关闭对话框。 The open() method of NgbModal returns an Observable when close() was called on the NgbActiveModal (as opposed to calling dismiss() on it). NgbModal 的open()方法在NgbModalNgbActiveModal close()时返回一个 Observable(而不是在其上调用dismiss() )。 If the operation was not successful, you should dispatch a failure action, and then re-open the dialog in another effect.如果操作不成功,你应该派发一个失败的动作,然后在另一个效果中重新打开对话框。

You can find a complete example repository showing the use of actions and effects: https://github.com/gflohr/ngbmodal-ngrx您可以找到一个完整的示例存储库,显示操作和效果的使用: https://github.com/gflohr/ngbmodal-ngrx

Additional explanations and comments: http://www.guido-flohr.net/angular-bootstrap-modals-with-ngrx/补充说明和评论: http://www.guido-flohr.net/angular-bootstrap-modals-with-ngrx/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM