Notifying child components which is active one

Viewed 114

Is there a better way to do the following? The following is spinning the CPU in Chrome (as per Javascript profiler).

<div *ngFor="let item of items">
    <itemComp [item]="item" [active]="item == service.activeItem"></itemComp>
</div>

Is there a way for each of the itemComp components to subscribe for a notification when they become active?

For ex., once they are rendered, let's say the user clicks on any of the items to mark as active. Only one item can be active any time. and say, I want to just change the background color of the active item to highlight it. In this case the current active item becomes inactive and a new item becomes active. How do I propagate this change?

2 Answers

Is there a way for each of the itemComp components to subscribe for a notification when they become active?

Do you mean when they get rendered the first time? If itemComp is your component, you can implement one of angulars lifecycle-hooks like ngOnInit and run your code there.

Edit: You could add a click event to each item with a function that:

<div *ngFor="let item of items">
    <itemComp [item]="item" [active]="item == service.activeItem" (click)="activateItem(item)"></itemComp>
</div>
  1. makes all items inactive
  2. makes the clicked item active

There are multiple ways to do it but I find subjects to be the most clean somehow.

Parent:

export const someEvent: Subject<Something> = new Subject<Something>();

export class someParentClass{

   public somethingHappened() {
      someEvent.next("something");
   }

}

In the child:

import { Subscription } from 'rxjs/Subscription';
import { someEvent } from './someParentClass';


export class SomeChildClass implements OnInit, OnDestroy{

    public someSubscription: Subscription;

    public ngOnInit(){
       this.someSubscription = someEvent.subscribe((something) => { 
              console.log("something happened" ,something); 
       });
    }

    public ngOnDestroy(){
       // if you don't do this then you'll have events firing off in components
       // that don't exist anymore
       this.someSubscription.unsubscribe();
    }

}

Just a small note about subjects vs event emitters. The thing about event emitters is it something that is created specifically for child/parent communication in @Output form. Subject hasn't got this "restriction" (performance issues) and thus can be used more widely even in services or repositories that are around your application. To boost there are many variations to subjects, such as async and behavior subject that all have small quirks that will fit a certain situation.

If you are using an @Output do use eventemitter, otherwise subject.

Related