My component (let's call it cmp) has change detection set to "onPush". Its template contains a <mat-menu> with projected content inside. In that content, some div has a click event handler toggleFooBar() {/* .. */} bound to execute a function from cmp component.
Because the click occurs within a mat-menu, I had do invoke $event.stopPropagation() within the toggleFooBar function to prevent the menu from closing.
To circumvent the fact that once propagation is prevented changeDetection does not appear to fire, I also call this.changeDetectorRef.detectChanges() within the click event handler. But call detectChanges() doesn't trigger any view update of the (still) opened menu despite the fact that toggleFooBar method alters a property used in the template (more precisely in the mat-menu projected content).
I finally managed to use an observable with a *ngIf construct but I still could not explain why the detectChanges call did not trigger the update of the mat-menu content.
<!-- dropdown.component.html -->
<mat-menu #menu="matMenu">
<ul>
<li>
<i class="glyph glyph-show"></i>
<span class="text" translate>FOOBAR</span>
<div (click)="toggleFooBar($event)" class="mode-switch" >
<div class="text-block" [ngClass]="fooClass" translate>xx.label</div>
<div class="switch-button color-b" [ngClass]="fooClass"></div>
<div class="switch-button color-g" [ngClass]="barClass"></div>
<div class="text-block" [ngClass]="barClass" translate>xx.label-alt</div>
</div>
</li>
<!-- Skipped for brevity -->
</ul>
</mat-menu>
<div
[matMenuTriggerFor]="menu"
#menuTrigger="matMenuTrigger"
></div>
// dropdown.component.ts
@Component({
/* ... */
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DropDownComponent
{
@ViewChild('menuTrigger') menuTrigger: MatMenuTrigger
public get fooClass() { return this.foobar == 1 ? '' : 'visible' }
public get barClass() { return this.foobar == 2 ? '' : 'visible' }
constructor(private cdr: ChangeDetectorRef) {}
public toggleFooBar($event: Event) {
$event.stopPropagation()
this.foobar = this.foobar == 1 ? 2 : 1
this.cdr.detectChanges() // <--- Shouldn't this call
} // trigger the view update?
// (trigger the evaluation of both
// "fooClass" and "barClass" getters)
/* ... */
}
stopPropagationis not blocking change detection from firing. Your problem lies somewhere else in your code. Please see the below stackblitz, where I added background color red to the visible class and on click thegetter/settermethods are getting toggled fine even without manually firing change detection!stackblitz