PX Developer
PX Developer

Reputation: 8145

Angular @Output: Can we detect if function is done when emitting?

I have an Angular Component with an Output. When I emit an event to this output, an async function will be called (this function is outside of the component).

Inside the component, I'd like to know when this outside function has finished. Is there any way to do that?

Here's some of the code of my component:

@Output() action: EventEmitter<string>;

itemClicked(item) {
    this.action.emit();
    // When the function of the observer is done: this.hideMenu();
}

And here's the code outside of the component:

<my-component (action)="getData()"></my-component>


getData() : Promise<any> {
    ...
}

Is there any way to detect that the "getData" function has finished inside of the component?

In AngularJS I could do it like this:

scope: {
    action: '&'
}
...

    scope.itemClicked = function(item) {
        $q.when(item.action()).finally(function() {
            scope.hideMenu();
        });
    };

EDIT:

I was thinking in another solution inspired by Ionic's refresher. What if the emit() call passes the instance of my component as a parameter? That way the getData function could do something like:

getData(menu): Promise<any> { 
    ...
    menu.hideMenu();
}

What do you think about this solution? If you think it's wrong then I guess I'll go with the Input.

Upvotes: 0

Views: 3829

Answers (3)

Estus Flask
Estus Flask

Reputation: 222498

AngularJS & binding was incorrectly translated to Angular. The proper counterpart is Input:

@Input() actionCallback: () => Promise<any>;

itemClicked(item) {
    this.actionCallback().then(...);
}

Which is used like:

<my-component [actionCallback]="getData">

While Output provides one-way interaction that isn't supposed to feed back. getData should be aware of its responsibilities and provide the feedback, through a callback or RxJS subject:

@Output() action: EventEmitter<Function>;

itemClicked(item) {
    this.action.emit(this.onClick);
}

onClick = () => {
  this.hideMenu();
}

Which is used like:

<my-component (action)="getData($event)"></my-component>

getData(callback) : Promise<any> {
    ...
    .then(callback);
}

Upvotes: 2

user4676340
user4676340

Reputation:

You can use the Host property to get the parent like so

@Output() action: EventEmitter<string>;

constructor(@Host() private parent: ParentComponent) {
    parent.getData().subscribe(...);
}

EDIT Type your parent as an abstract class

constructor(@Host() private parent: ConcernedParent) {
    parent.getData().subscribe(...);
}

export abstract class ConcernedParent {
  public abstract getData(): Observable<any>;
}

Upvotes: 0

Fabio Carpinato
Fabio Carpinato

Reputation: 1181

I think you should use an @Input to send the completed message when the function is done and in the interested component listen for the input with the set and do what you want knowing that the function is completed.

Upvotes: 5

Related Questions