Skip to content

Better ngClass typings #39280

Closed
Closed

Description

@dev054

🐞 bug report

Affected Package

@angular/common.

Is this a regression?

In ng < 9, the type was any so it worked.

Description

set ngClass(value: string|string[]|Set<string>|{[klass: string]: any}) {

Actually we can't pass readonly arrays or readonly sets with strictTemplates enabled, because the current types don't support it.
Another thing that is really trivial is that we can't use right now it with | async, as it could return null | undefined and it's also not supported.

🌍 Your Environment

Angular Version:

Angular CLI: 10.1.6
Node: 13.7.0
OS: darwin x64

Angular: 10.1.5
... animations, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1001.6
@angular-devkit/build-angular   0.1001.6
@angular-devkit/core            10.1.6
@angular-devkit/schematics      10.1.6
@angular/cdk                    10.2.4
@angular/cli                    10.1.6
@schematics/angular             10.1.6
@schematics/update              0.1001.6
rxjs                            6.6.3
typescript                      4.0.3

Activity

  1. Airblader commented on Oct 15, 2020

    @Airblader
    Contributor

    If you need a temporary workaround you can wrap what you're passing to ngClass in $any():

    [ngClass]="$any({...})"
    
  2. added
    area: commonIssues related to APIs in the @angular/common package
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    on Oct 15, 2020
  3. added this to the Backlog milestone on Oct 15, 2020
  4. mofogasy commented on Jul 12, 2021

    @mofogasy

    Do you have any update on this, as this issue is still present in 12.1.0.

    Angular CLI: 12.1.0
    Node: 14.17.0
    Package Manager: npm 6.14.13
    OS: win32 x64
    
    Angular: 12.1.0
    ... animations, cdk, cli, common, compiler, compiler-cli, core
    ... forms, platform-browser, platform-browser-dynamic, router
    
    Package                         Version
    ---------------------------------------------------------
    @angular-devkit/architect       0.1201.0
    @angular-devkit/build-angular   12.1.0
    @angular-devkit/core            12.1.0
    @angular-devkit/schematics      12.1.0
    @schematics/angular             12.1.0
    ng-packagr                      12.1.0
    rxjs                            6.6.7
    typescript                      4.3.4
    
  5. petebacondarwin commented on Jul 12, 2021

    @petebacondarwin
    Contributor

    I can reproduce this problem for null but not for readonly arrays and maps.

    I created a new Angular project using the CLI (12.1.1) and changed the AppComponent to be:

    @Component({
      selector: 'app-root',
      template: `
      <p [ngClass]="stringClasses">xxx</p>
      <p [ngClass]="mapClasses">yyy</p>
      <p [ngClass]="setClasses">zzz</p>
      `,
      styles: ['.a { color: red; }']
    })
    export class AppComponent {
      stringClasses: readonly string[] = ['.a {color: red}'];
      mapClasses: ReadonlyMap<string, boolean> = new Map([['a', true]]);
      setClasses: ReadonlySet<string> = new Set(['a']);
    }

    In the tsconfig.json, I added:

      "angularCompilerOptions": {
        ....
        "strictTemplates": true
      }
    

    And when I run ng build I do not get template type check errors.

    Am I missing something?

  6. mofogasy commented on Jul 12, 2021

    @mofogasy

    I did not try for read-only arrays and maps, but values which can be undefined (and also the async pipe, because it might return undefined) it does not work, e.g.:

    @Component({
      selector: 'app-root',
      template: `
      <p [ngClass]="stringOrUndefinedClass">xxx</p>
      <p [ngClass]="observableClass$ | async">yyy</p>
      `,
      styles: ['.a { color: red; }']
    })
    export class AppComponent {
      stringOrUndefinedClass: string | undefined = '...';
      observableClass$: Observable<string> = of('...');
    }
    
    
  7. petebacondarwin commented on Jul 12, 2021

    @petebacondarwin
    Contributor

    One workaround for the async case would be {{ (obs$ | async) || '' }}.

  8. imirkin commented on Jul 10, 2022

    @imirkin
    Contributor

    Running into this myself with undefined when trying to enable strictTemplates... seems like a fix would be trivial. Has anyone tried submitting one and had it rejected?

  9. angular-automatic-lock-bot commented on Sep 1, 2022

    @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 Sep 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: commonIssues related to APIs in the @angular/common packagecross-cutting: types

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions