Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know if component is currently the loaded component in router-outlet

I have an application with lazy loaded modules.

In one specific lazy loaded module, I have a parent component, which has router-outlet.

In that parent component I have a button which basically emit an event using a shared service (provided on the lazy loaded module).

each child component (which is loaded in router-outlet) is subscribing to that event using the same shared service!

I tried to recreate my use case in the following plunkr using heroes demo.

Open Dev tools to see console messages.

  • Click on Heroes Link (it should be selected by default).
  • Click on Hero Item from the list.
  • Click on Admin Link.
  • Click On Emit Test button (upper right nav)

You'll see -in the console- that Event was received by both components, even both components should not be 'Active' !!!

1) Is this by design?

2) How to know if the current Component is the active one?


SUMMARY/UPDATE

From my understanding, EventEmitter/Subject can be subscribed as many times, but when unsubscribed you cannot use it/subscribe to it AFAIK.

My solution was:

1) in service I ended doing the folowing:

get(){
  if (!this.testEvent.closed) {
      this.testEvent.complete();
      this.testEvent.unsubscribe();
    }
    this.testEvent= new EventEmitter<void>();
    return this.testEvent;
  }
}

2) In each component I subscribe to the event, I added ngDestroy and unsubscribed the event:

  ngOnDestroy() {
    this.testEvent.unsubscribe();
  }
like image 894
A.Akram Avatar asked Nov 06 '16 08:11

A.Akram


People also ask

Which contains the information about a route associated with a component loaded in an outlet?

ActivatedRoutelink. Provides access to information about a route associated with a component that is loaded in an outlet.

Is router outlet a component?

Router outlet is a dynamic component that the router uses to display in this case either the Home or the AllLessons components.

Can you identify the use of router outlet directive?

Router-Outlet is an Angular directive from the router library that is used to insert the component matched by routes to be displayed on the screen.


2 Answers

You have a service, which is a singleton. This service exists from the beginning of the application until its end.

You have two components. These are not singletons. They are created when they must be displayed on a page, and destroyed when they must not be anymore.

And, when the components are created, you subscribe to an observable inside the singleton service. What does it mean? It means that the observable needs to keep a reference to your observer, which itself has an emplicit reference (this) to the component instance. Without that reference, the observable wouldn't be able to call the observer when an event is emitted. So, even though Angular doesn't need your component instance anymore, the observable still has a reference to it, and calls it when an event is emitted.

You thus need to unsubscribe when the component is not needed anymore:

private subscription: Subscription;

ngOnInit() {
    this.subscription = this.service.getTestEvent().subscribe(...);
}

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

Without doing that, not only do you have observers called for nothing, making the app slower, but you also have a memory leak.

like image 102
JB Nizet Avatar answered Oct 03 '22 05:10

JB Nizet


The point is that you never unsubscribe the event. The more you click your users the more you will see lines in the console. Any time you click you subscribe to the event, i.e. you add a callback that will get executed any time the event is raised, unless you unsubscribe. In the method ngOnDestroy() you should call the unsubscribe() method on the subscription (which is the object returned by the subscribe() method).

In other words something like this

subscrition: Subscription;

ngOnInit() {

    this.subscription = this.service.getTestEvent().subscribe( (e) => {
      console.log('HeroListComponent ==>');
    });

.....

}

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

I hope this helps.

like image 31
Picci Avatar answered Oct 03 '22 05:10

Picci