I'm trying to use the [ngStyle] directive in an Angular 17 app to dynamically show or hide an element, like this:
<div [ngStyle]="{visibility: loaded ? 'collapse' : 'visible' }">
...
</div>
where loaded
is a boolean property in my component.
The problem is: this doesn't work. It correctly sets the visibility
property at the start according to the initial value of loaded
, but after that if I at some point change the value of loaded
the visibility doesn't change accordingly. Am I missing something basic here? I've also tried with [style]
instead of [ngStyle]
but the result is exactly the same.
Edit: here's my imports in the component:
imports: [
NgIf,
ProgressBarModule,
NgStyle,
CommonModule
],
EDIT 2: after further testing, it seems that Angular is not detecting the change in the loaded
property for some reason.
If I inject ChangeDetectorRef
into the component and manually trigger change detection, like this:
this.loaded = true;
this.cdRef.detectChanges();
it start working correctly.
Note that the code that flips the loaded
property is inside a Promise
... can that be the issue? Are changes made inside a Promise
block not auto-detected by Angular in general?
You have OnPush Change detection strategy enabled.
This triggers change detection only when @Inputs
of a component or browser/user events (button click)
Read about it in details on the angular docs
That is why the asynchronous call is not updating the UI and you have to do this.cdRef.detectChanges();
Make sure you imported either CommonModule
or NgStyle
directive into the component only then will the directive work.
CommonModule contains the directives needed for using NgStyle
or NgClass
.
...
@Component({
selector: '...',
standalone: true,
imports: [CommonModule],
...
})
export class SomeComponent {
...
If it's standalone -> the imports should be in the imports array of the component.
If it's modular -> go to the module, where the component is added to the declarations array and add the import.