New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support binding component outputs as callbacks #12630
Comments
So, thinking about this more, the general problem is that there is no simple way to declaratively provide a callback/delegate to a child component in such a way that the callback can also be supplied with template variables. Consider my <form #f="ngForm">
...
<async-button (action)="submitForm(f)">
Submit Form
</async-button>
</form> As stated earlier, there is no easy way for In something like React's JSX, this isn't a problem, as an arrow function could be passed as an input: <AsyncButton action={ () => submit(form) } /> But this won't work in Angular 2, as arrow functions are not supported in template expressions. Still, there are a few of ways to achieve this using the existing Angular 2 template syntax: 1 — Make <async-button [action]="[submitForm, f]"> @Input() public action: any[];
public onAction() {
let result = this.action[0].apply(this.action.slice(1));
... // do something with result.
} The downside of this approach it is non-obvious from looking at the template that this represents a call. 2 — Make the EventHandler synchronous, and make the <async-button (action)="$event(submitForm(f))"> @Output() public action: EventHandler<any> = new EventHandler(false);
public onAction() {
let result;
this.action.emit(r => result = r);
... // do something with result.
} The downside is that it feels a little weird and non-obvious to be using 3 — Have a function in the parent controller that accepts the template variables as parameters and creates a callback function that can be bound to an <async-button [action]="createSubmitCallback(f)"> public createSubmitCallback(form: NgForm) {
return () => this.submitForm(form);
} The drawback is that change-detection is going to keep triggering a re-evaluation of Possible Improvements 1 — Allow arrow functions in <async-button [action]="() => submitForm(f)"> @Input() public action: () => ResultType; This has a nice parity with React and modern JS. 2 — Add a new decorator type, called <async-button (action)="submitForm(f)"> @Delegate() public action: () => ResultType; The drawback of this is that it isn't obvious from looking at the template whether something is bound as delegate or an event. |
So you are missing:
Let's put aside liking / not liking the RxJS approach, the missing feature is not being able to get the result of actions, right? |
@tbosch Yes, exactly. |
I have a component which is something like this: I want to make a http call onNext and then once I get the response I would like to excute rest of the function. onNextInternal(event) { Can we achieve something similar or I need to wait for this bug to get fixed? |
@vikrambhatla ... re-order of your code ... and finally call |
@mlc-mlapis it won't work, as emit needs to be called before suscribe. this.onNext.emit(); |
I solved this by creating an observable that is passed into the emit. For example const observable: Observable<any> = Observable.create((observer) => {
this.onNext.emit(observer);
});
observable.subscribe((response) => {
//go to next step
}, (error) => {
//stay at current step
}); Hopefully this helps. |
Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends. Find more details about Angular's feature request process in our documentation. |
Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage. We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package. You can find more details about the feature request process in our documentation. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
I'm submitting a ... (check one with "x")
Current behavior
In Angular 1, I had a directive called
async-action
:The directive would register a click listener on the host. When the host was clicked, the directive would call the event handler.
The event handler could optionally return a promise, and the directive would apply animations to the host element based on the promise lifecycle. The flow was roughly this:
This pattern was an simple and expressive way for directives/components to declaratively delegate parts of their lifecycle to their consumers. Unfortunately, it does not appear to be supported in Angular 2. Event binding is far more limited and inflexible, being tied to the class EventEmitter, which requires an RxJS approach and precludes returning results from handlers.
Expected behavior
Angular 2 should support callback bindings to callbacks. E.g. if my component class looks like this...
...then Angular should assign the statement call from the template directly to the field.
What is the motivation / use case for changing the behavior?
Expressiveness, productivity and Angular 1 parity.
Angular version:
2.1.1
Browser:
All
Language:
All
The text was updated successfully, but these errors were encountered: