Skip to content

Conversation

@crisbeto
Copy link
Member

@crisbeto crisbeto commented Jan 2, 2026

Adds support for using arrow functions in Angular expressions. They generally behave like JS arrow functions with the same access as other Angular expressions, but with the following limitations:

  • We only support arrow functions with implicit returns, e.g. (a) => a + 1 is allowed while (a) => { return a + 1 } is not.
  • Pipes can't be used inside arrow functions, but they can be passed through to pipes.

To avoid recreating the functions in each change detection, the compiler generates an instruction that caches the function after it's referenced for the first time.

Fixes #14129.

@crisbeto crisbeto added action: review The PR is still awaiting reviews from at least one requested reviewer target: minor This PR is targeted for the next minor release labels Jan 2, 2026
@angular-robot angular-robot bot added detected: feature PR contains a feature commit area: compiler Issues related to `ngc`, Angular's template compiler area: core Issues related to the framework runtime labels Jan 2, 2026
@ngbot ngbot bot modified the milestone: Backlog Jan 2, 2026
@crisbeto crisbeto marked this pull request as ready for review January 2, 2026 13:30
Comment on lines +3328 to +3384
template: `<button (click)="value.update(prev => prev + 1)">Increment</button>`,
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you given any thoughts of what we might want to do when users write (click)="() => { ... }".
I could see that happening because of how events handlers are written in JSX.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean supporting an arrow function that returns an object literal?

Copy link
Member

@JeanMeche JeanMeche Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more thiking about the cases where users write an uninvoked arrow function passed to a template event listener.

(click)="() => mySignal.set(0)"

will result in a noop and it might catch developers of guard.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. Seems like a good candidate for an extended diagnostic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this perhaps also a chance to get rid of the magic $event in event bindings?

I'm thinking on

(event) => doStuff(event)

vs.

doStuff($event);

@crisbeto
Copy link
Member Author

crisbeto commented Jan 9, 2026

Passing TGP

Adds some logic to tokenize the `=>` character combination in the lexer.
Expands the expression AST to include arrow functions.
Updates the expression parser to handle arrow functions. Since arrow functions share syntax with other AST nodes, we have to detect them by looking ahead and then potentially jumping backwards depending on what we see.
…tions

Updates the template type checker to support arrow functions. The main challenge was getting the current infrastructure not to rewrite references to arrow function parameters.
Adds the `ɵɵstoreCallback` instruction that allows for a callback to be stored for later usage, as well as `ɵɵgetCallback` which can be used to retrieve it.
The `countVariables` phase visits all ops in the list and all nested expressions in order to count how many variables are used. Currently it does so by going through `unit.ops()` and then calling `visitExpressionsInOp` on each op.

This leads to expressions in ops that have nested ops (e.g. `ListenerOp`) to be visited twice, because `unit.ops()` descends into child ops and then `visitExpressionsInOp` does the same. It hasn't been a problem so far, because the only expressions that can have vars in host bindings are pure functions and they aren't generated for listeners, but it will become a problem for arrow functions since they can be used in listeners.

These changes resolve the issue by iterating over the `unit.create` and `unit.update` instead.
Adds support for using arrow functions in Angular expressions. They generally behave like JS arrow functions with the same access as other Angular expressions, but with the following limitations:
* We only support arrow functions with implicit returns, e.g. `(a) => a + 1` is allowed while `(a) => { return a + 1 }` is not.
* Pipes can't be used inside arrow functions, but they can be passed through to pipes.

To avoid recreating the functions in each change detection, the compiler applies a couple of optimizations:
* If an arrow function only references its own parameters, it is extracted into a top-level constant that is passed around to the different usage sites.
* If an arrow function has references to the template context, we store it on the current view and read the stored value later on.

Fixes angular#14129.
Reworks how we store arrow functions in the following ways:
1. Rather than the `storeCallback` and `getCallback` instructions, we generate a single `arrowFunction` instruction.
2. The `arrowFunction` instruction uses a factory to create a new instance of the function when a function is read for the first time.
3. We now keep arrow functions in listeners in line so that they have access to `$event`.
Isolates the logic that fixes references to arrow function parameters so that we don't have do pass extra parameters for every `convertAst` call.
@crisbeto crisbeto added action: merge The PR is ready for merge by the caretaker and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Jan 9, 2026
@thePunderWoman thePunderWoman merged commit 7b5625e into angular:main Jan 9, 2026
20 checks passed
@thePunderWoman
Copy link
Contributor

This PR was merged into the repository. The changes were merged into the following branches:

@toverux
Copy link

toverux commented Jan 9, 2026

Wow, just a thank you for implementing this almost-a-decade-old feature request! That will be very nice for QoL.

@JeanMeche
Copy link
Member

FYI this was merged in the branch for v21.2 which will be released mid-febuary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: merge The PR is ready for merge by the caretaker area: compiler Issues related to `ngc`, Angular's template compiler area: core Issues related to the framework runtime detected: feature PR contains a feature commit target: minor This PR is targeted for the next minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support arrow functions in template syntax

5 participants