Search code examples
angularoutputobservableangular-componentseventemitter

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.


Solution

  • 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);
    }