Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: How do I emit an event up through multiple nested components?

Tags:

angular

I have one "smart" component called ItemsComponent and two nested "dumb" components, ItemsListComponent and ItemComponent.

ItemsComponent's html template contains ItemsListComponent.

// ItemsComponent
<div>
  // ItemsListComponent
  <app-items-list
    [items]="items"
    (doDelete)="deleteItem($event)"
  >
  </app-items-list>
<div>

and it has a function called deleteItem:

deletItem(item) {
  // code to handle item deletion...
}

ItemsListComponent contains ItemComponent:

// ItemsListComponent    
<ul *ngFor="let item of items">
  // ItemComponent
  <app-item
   [item]="item"
   (doDelete)="deleteItem($event)"
  >
  </app-item>
</ul>

So the html structure is like this:

ItemsComponent (app-items)
    - ItemsListComponent (app-items-list)
        - ItemComponent (app-item)

ItemComponent has a button

<button (click)="deleteItem(item)">

and an event emitter for deleteItem:

@Output() doDelete = new EventEmitter();

deleteItem(item) {
  this.doDelete.emit(item);
}

When the delete button is clicked in ItemComponent, the event only bubbles up to it's immediate parent, ItemsListComponent, but doesn't make it to ItemsComponent unless I add identical event emitter functionality to the ItemsListComponent.

Smelly ItemsListComponent:

@Output() doDelete = new EventEmitter();

deleteItem(item) {
  this.doDelete.emit(item);
}

It works this way, but ItemsListComponent now shares code smell with ItemsComponent since they both have the same event emitter stuff and the event has to be passed from one component to another on it's way up.

Is there a better way to do this?

like image 339
Tyson Avatar asked Mar 21 '17 04:03

Tyson


People also ask

Which emit event and pass data to container component from child component?

A decorator emits an event up to a parent component using event binding. The parent component should have a function that accepts the data emitted from the child component. It gets the data before calling the ngOnInit() method.


1 Answers

As you've realised, custom angular events don't bubble, so if you have a deeply nested component and you want to pass an event to a higher component, every component in between has to delegate the event upwards.

Another option is to move your deleteItem functionality to a service that is injected into one of your lower level components. That way, the function can be called at the point where it happens, rather than having to bubble the event up your view hierarchy.

like image 138
snorkpete Avatar answered Sep 30 '22 18:09

snorkpete