Home > Mobile >  Angular 9 (Ivy): CSS class^ attribute selectors stops working with angular material components
Angular 9 (Ivy): CSS class^ attribute selectors stops working with angular material components

Time:12-16

I am currently updating an Angular project from v8 to v9, and I have discovered an issue with using CSS class attributes together with Angular Material components. I have also updated to Material v9.

With this simplified HTML,

// Example List 1
<mat-nav-list >
  <mat-list-item> SOME HTML.. </mat-list-item>
</mat-nav-list>

// Example List 2
<div >
  <mat-list-item> SOME HTML.. </mat-list-item>
</div>

the following SCSS,

[class^="example-list"] {
  mat-list-item {
    SOME SCSS..
  }
}

is only adding style to the <mat-list-item> in Example List 2, where <div> is being used.

It works fine if I, for example, use id instead of class in both HTML and SCSS, but I would prefer not to have to do a lot of tinkering with the code.

Update

I have also found out it works fine if I disable Ivy.

"angularCompilerOptions": {
    "enableIvy": false
 }

Why is it not working with Ivy? Is this expected behavior?

CodePudding user response:

I think you faced a bug that was introduced with Ivy https://github.com/angular/angular/issues/33111

The issue here is the wrong order of adding css classes.

MatNavList component has a host property binding within metadata:

@Component({
  selector: 'mat-nav-list',
  host: {
    'role': 'navigation',
    'class': 'mat-nav-list mat-list-base',
  },
  ...
})
export class MatNavList

https://github.com/angular/components/blob/74685883ec16782d172a4505348eef6f2003a31b/src/material/list/list.ts#L66

Before Ivy your class was added first to class attribute of element:

<mat-nav-list 

with early Ivy version it became the last added class:

<mat-nav-list 

As a result your selector doesnt work for second case. But there is an alternative:

[class*="example-list"] {
  ...
}
  • Related