Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Child component events broadcast to parent

I'd like to implement the common Angular 1.x pattern of having child directives within a parent directive in Angular 2. Here's my desired structure.

<foo>
  <bar>A</bar>
  <bar>B</bar>
  <bar>C</bar>
</foo>

I'd like for these Bar components to have click events that get emitted to the Foo component.

Here's my Foo so far:

@Component({
  selector: 'foo',
  template: `
    <div>
      <ng-content></ng-content>
    </div>
  `
})
export class Foo {
   @ContentChildren(Bar) items: QueryList<Bar>;
}

And here's my Bar:

@Component({
  selector: 'Bar',
  template: `
    <div (click)="clickity()">
      <ng-content></ng-content>
    </div>
  `
})
export class Bar {
  clickity() {
    console.log('Broadcast this to the parent please!');
  }
}

How do I go about notifying Foo whenever one of its Bars is clicked?

like image 875
Jack Guy Avatar asked Jan 15 '16 00:01

Jack Guy


People also ask

How do you communicate between parent and child components?

@Input() and @Output() give a child component a way to communicate with its parent component. @Input() lets a parent component update data in the child component. Conversely, @Output() lets the child send data to a parent component.

How do you call a function on a child component on parent events?

To call function on child component on parent events with Vue. js, we can assign the ref to the child component and then call the method in the parent when the event is emitted. to add a template with the child-component added. We assign a ref to it.

Which decorator lets a child component expose an event to a parent component?

So to emit an event from the child component class to the parent component class, use EventEmitter with the @Output() decorator.


1 Answers

You can use a service to send data between components if you can't do it using @Output() decorator. Here's an example:

import {EventEmitter} from 'angular2/core';

export class EmitterService {
  private static _emitters: { [channel: string]: EventEmitter<any> } = {};
  static get(channel: string): EventEmitter<any> {
    if (!this._emitters[channel]) 
      this._emitters[channel] = new EventEmitter();
    return this._emitters[channel];
  }
}

You import it wherever you need to emit or subscribe to an event:

// foo.component.ts
import {EmitterService} from '../path/to/emitter.service'

class Foo {
  EmitterService.get("some_id").subscribe(data => console.log("some_id channel: ", data));
  EmitterService.get("other_id").subscribe(data => console.log("other_id channel: ", data));
}

// bar.component.ts
import {EmitterService} from '../path/to/emitter.service'

class Bar {

  onClick() {
    EmitterService.get("some_id").emit('you clicked!');
  }
  onScroll() {
    EmitterService.get("other_id").emit('you scrolled!');
  }
}

another example: plunker

like image 181
Sasxa Avatar answered Oct 13 '22 08:10

Sasxa