Skip to content

Support spread operator (...) in Angular templates (e.g., for [class] binding) #61800

Closed

Description

@RSamaium

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

It would be very useful to allow the use of the JavaScript spread operator (...) within Angular templates, especially for object bindings like [class], [style]

Current Behavior:

Using the spread operator in object literals within templates results in a parser error:

NG5002: Parser Error: Unexpected token

For example:

<div [class]="{ 'pt-16': nb, ...css }"></div>

This currently throws an error.

Workaround:

Currently, we need to do the merging in the component class:

get mergedClasses() {
  return { 'pt-16': this.nb, ...this.css };
}
<div [class]="mergedClasses"></div>

While this works, it adds verbosity and requires additional logic in the component when the operation could be handled declaratively in the template.

Proposed solution

Allow the use of the spread operator in Angular template expressions, so the following syntax becomes valid:

<div [class]="{ 'pt-16': nb, ...css }"></div>

This would provide more expressive and concise template code, especially when merging static and dynamic classes or styles.

Alternatives considered

None

Activity

  1. added this to the needsTriage milestone on Jun 1, 2025
  2. JeanMeche commented on Jun 1, 2025

    @JeanMeche
    Member

    Closely related is #14545 (and #43485 as a more canonical one).

    Support for class/style bindings is more straightforward than for inputs/outputs (see the generated instructions), but the question is more do we want to introduce partial support of the spread-operators.

  3. RSamaium commented on Jun 1, 2025

    @RSamaium
    Author

    Thank you for the feedback.

    Here, the approach is to have a standard JavaScript object, rather than using a specific syntax in the templates.

    We could simply support the spread operator in a regular object.

    We can handle this on the TypeScript side — the question is, if we can do it in TS, why not allow it directly in the templates?

  4. JoostK commented on Jun 1, 2025

    @JoostK
    Member

    One challenge here is that Angular optimises binding expressions to avoid allocations when none of the values have changed. E.g. { a: 'test', b: variable } only creates the object when variable has changed. With spread syntax supporting iterables this may be difficult as you'd have to iterate the iterable to learn whether it has changed, incurring an allocating of an intermediate array to collect all iterated values (or you'd have to iterate twice, but that won't work for iterators)

  5. RSamaium commented on Jun 1, 2025

    @RSamaium
    Author

    Thanks for the clarification,

    Right now, we can:

    <div [class]="css"></div>

    but I don't see how the spread would be problematic.

    <div [class]="{ ...css }"></div>

    The compiler interprets the same result, doesn't it?

  6. JeanMeche commented on Jun 1, 2025

    @JeanMeche
    Member

    Without the check that joost mentions, { ...css } would create a new object everytime CD runs (= every time the template function runs).

  7. alxhub commented on Jun 3, 2025

    @alxhub
    Member

    I would imagine we apply the same rules: {...css} only updates when the css value changes. That is, we wouldn't iterate/diff its iteration.

  8. self-assigned this
    on Dec 21, 2025
  9. angular-automatic-lock-bot commented on Feb 7, 2026

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  10. locked and limited conversation to collaborators on Feb 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions