Search code examples
angulartypescriptngrx

Passing payload between actions in Angular/Ngrx


I am a newbie in the Angular/Ngrx world, and I am using it in an application as below. I will try to explain the issue as best as I can.

We have a main page that has 2 components - a configuration page, and a confirmation alert (initially hidden). The user can change configuration and the state of the page is stored in a MyPageConfig object. On clicking "Save" on this page, an action is triggered and the confirmation alert is shown. On clicking "Confirm" on the alert, the data should be persisted by calling a backend API.

I have this in the HTML of the main page:

<ng-template #whenLoaded> 
  <configure-page [doSubmitForm]="submitForm"></configure-page>        
  <confirm-delete [remove-config]="removeConfig$" 
            (onCancel)="handleCancel()" (onConfirm)="handleConfirm()"></confirm-delete>            
</ng-template>

removeConfig$ is a boolean Observable I am listening to, but not making use of at this time.

I have these following 2 handlers in the TS file of the main page:

handleCancelRemove() {
    this.store.dispatch(new actions.CancelRemoval());
}

handleConfirmRemove() {
    this.store.dispatch(new actions.ConfirmRemoval());    
}

Note that no payload is being sent to handleConfirmRemove since this page itself is unaware of the configuration changes.

In the doSubmitForm handler of the configuration page, I am showing the confirmation message dialog as this:

if (some condition) {
    this.store.dispatch(new actions.ShowConfirmationDialog());
    // Here we have the payload and can use it somehow? 
    // But the "confirm" button click is handled in the TS of the main page.
}

It shows the dialog. But I am stuck on how to pass the configuration payload to persist it. I can write an effect, but in order to do this, I need the ConfirmRemoval() action to pass the payload which happens to be on the main page.

In my mind there are 2 potential solutions, but I do not know how to work them out:

  1. Pass the payload from the child (config) page to the parent (main) page, and it will submit it with the action handler for the confirmation button click.
  2. Have the parent (main) page be aware of the config changes (i.e. the form state), and it creates and submit the payload directly with the action handler for the confirmation button click.

Any suggestion on how this can be accomplished will be greatly appreciated.


Solution

  • This is very common usecase and I would actually listen to confirmation dialog result and act accordingly. The fact you are doing everything via a single event bus will kind of obfuscate logic, but it is doable.

    if (some condition) {
      const payload=wegotthepayload.
      this.showDialog().subscribe(resultOfDialog=>{
          if(resultOfDialog=='okClicked'){
             this.saveThePayloadSomehow(payload);
          }else {
             do something else or ignore.
           }
       }))
    }
    

    Where this.showDialog() is a method that opens dialog and returns Observable<ResultOfDialog>

    This can be done by eg emiting Ok/Cancel event to on your event bus and just filtering the events (pipe + filter)

    It could be like

    showDialog(){
            this.store.dispatch(new actions.ShowConfirmationDialog());
           return this.store.yourEventsStream().pipe(filter(e=>e=='okClicked' || e=='cancelClicked'),take(1));
    

    and obviously your dialog would have to emit proper events accordingly.

    }