Nik
Nik

Reputation: 7192

How to use EventEmitter from child component with observable in parent (angular 2)

I have a child component that emits a number:

this.number.emit(3);

In the parent component I listen to it:

<parent>
  <child (number)="$event"></child>
</parent>

In the parent class, how do I combine the EventEmitter from the child component with an observable in the parent component?

this.apiService.getSomeHTTPRequest()
    .combineLatest(--- ??? combine with child event emitter ??? ---)

Upvotes: 3

Views: 6519

Answers (3)

Shalom Peles
Shalom Peles

Reputation: 2632

Since that every EventEmitter is actually an Observable (Subject to be precise), you can subscribe to it (or combine it with other observables).

You should get the child component:

@ViewChild(ChildComponent, { static: true }) child: ChildComponent;

And then, you can subscribe (or combine) to the EventEmitters of the child:

child.number.subscribe();

Using this technique, you do not need to listen to the event in the template:

<parent>
  <child></child>
</parent>

StackBlitz

Upvotes: 0

Madhu Ranjan
Madhu Ranjan

Reputation: 17904

Try below,

@Component({
  selector: 'my-app',
  template: `<h1>Hello {{name}}</h1>
  <my-child (number)="childNumber.next($event)" ></my-child>
  `
})
export class AppComponent {
  name = 'Angular';
  childNumber: Subject<any>= new Subject<any>();

  someAPI = Observable.interval(2000);
  combined = Observable.combineLatest(this.childNumber,this.someAPI);

  constructor(){
    this.combined.subscribe(latestVals => console.log(latestVals));
  }
}


@Component({
  selector: 'my-child',
  template: `<h3>Child Component</h3>`
})
export class ChildComponent { 
  @Output() number: EventEmitter<any> = new EventEmitter<any>();

  constructor(){
    Observable.interval(1000).subscribe(num => {
      this.number.emit(num);
    });
  }
}

Check this Plunker!!

Hope this helps!!

Upvotes: 2

Mateusz Kocz
Mateusz Kocz

Reputation: 4602

You have to manually create a Subject in the parent component. You will need to feed this subject with data from the emitted event and use it in the combineLatest method. The implementation will look like that:

import Subject from 'rxjs/Subject'
@Component({
    // Forward events from the child component to the numberChanges subject.
    template: `<child (number)="numberChanges.next($event)"></child>`
})
class Parent {
    numberChanges = new Subject<number>()
    // Assuming you create the stream in onInit method.
    ngOnInit() {
         const stream = this.apiService.getSomeHTTPRequest()
             // Combine the numberChanges stream.
             .combineLatest(this.numberChanges)
    }
}

Upvotes: 5

Related Questions