Search code examples
angularangular5observableangular2-directiveseventemitter

Pass event to directive and subscribe to it


I have a directive which has an Output of EventEmitter. I would like to do something when the subscription of the emitted event returned subscription is completed.

(for example, I would like to do console.log('test') when save() of example.component is completed. - I am aware I can do that in the example.component's save method but I am doing something generic so I need it in the directive).

import { Directive, OnInit, HostListener, Output, EventEmitter } from '@angular/core';

@Directive({
  selector: '[appSingleActiveButton]'
})
export class SingleActiveButtonDirective {
  @Output() appSingleActiveButton: EventEmitter<any> = new EventEmitter();

  constructor() {}

  @HostListener('click', ['$event'])
  private onClick(e: any): void {
    this.appSingleActiveButton.next(e);
    //determine somehow that the referred function's subscription is completed and do something
    // for example what I tried is: this.appSingleActiveButton.subscribe(() => console.log('do some other stuff'))
  }
}

and I have a component which has an element with that directive and pass a function which returns Subscription.

example.component.ts:

import { Component } from '@angular/core';
import { Subscription } from 'rxjs/Rx';
import { Http } from '@angular/http';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.scss'],
})
export class ExampleComponent {

  constructor(private http: Http) {}

  public save(index: number): Subscription {
    const requestUrl = 'http://example.com';
    return this.http
    .get(requestUrl)
    .map((response) => response.json()).subscribe(() => console.log(`doing some stuff ${index}`));
  }
}

example.component.html

<div *ngFor="let btn of btns; let i = index">
    <div (appSingleActiveButton)="save(i)">test directive</div>
</div>

EDIT: The question is as follows:

How can I determine that the save() is completed (either success or error) inside the directive where I actually call it this.appSingleActiveButton.next(e);


Solution

  • Following my previous answer and your explanation, I got your issue right this time.

    For your solution, you have several ways of doing what you want.

    1. Given the directive only makes the same thing (HTTP calls)

    For that, you can simply pass the URL as a parameter to your directive, and let the direcdtive handle the HTTP call. You can use an @Output to retrive the subscription and subscribe to it in your component.

    1. Given that they do slightly similar things and want to keep the logic into your component

    You can pass your function save directly as an @Input to your directive. On click, you can run this function, and again, use an @Output to get the subscription.

    You can also directly take the reference to your element in the constructor, and on click, call the function of that element.

    Those are the solutions you can implement. If you need help on the code, feel free to ask for it, but I don't give it to you like that because I'm not your code monkey, and trying is the best way to learn.