Search code examples
angularobservablesubscriptioneventemitterondestroy

angular2 destroying subscriptions on view destroy


I have an "appService" which i Use to handle the interaction between all my components (forms, navigations, etc).

My service has many event emitters to which the components subscribe (results showing, element selected, form posted, and so on).

When a new view is displayed, it subscribes to the appService events it needs to. Now the problem is when i navigate to another view (form), the no longer needed view is destroyed, but its subscriptions still get called...! I find referencing all subscriptions and unsubscribing explicitly a massive boilerplate for a simple task. What am I doing wrong? how to siplify this?

Example code:

export class VendorsForm {
    constructor(private appService: AppServiceMain)
    {
            this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {
            //detailed view of this item
            this.model = selectedEntity;
            this.appService.setFormIsShowingDetail();
        })
    });

    }
}

now in another component:

export class CustomersForm {
    constructor(private appService: AppServiceMain)
    {
            this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {
            //detailed view of this item
            this.model = selectedEntity; this.appService.setFormIsShowingDetail();
        })
    });

    }
}

Just as a reference, here's the service and the event invoking components:

export class AppServiceMain {
    public onSearchResultSelected$: EventEmitter<IEntity>;
        setSelectedEntity(ent: IEntity)
        {
            this.formstate = states.EntitySelected;
            this.onSearchResultSelected$.emit(ent);
        }

event invoking component

export class ResultsComponent { 
    rowDblClick(ev$)
    {
        this.appService.setSelectedEntity(ev$.data);
    }

I DO understand how to remove these suscriptions if I want to. The problem is my forms are quite big and functional and I have tons of non standard references, Isnt there a way to automatically stop listening when the view gets destroyed? I find manually destroyng all these to be quite error prone.


Solution

  • If you subscribe imperatively, then also unsubscribe imperatively

     this.someSubscription = this.appService.onSearchResultSelected$.subscribe((selectedEntity) =>
    
    ngOnDestroy() {
      this.someSubscription.unsubscribe();
    }
    

    See also how to unsubscribe several subscriber in angular 2