Issue
I have a complex MatMenu
with more MatMenuItem
. Each MatMenuItem
's visibility is based on a condition. The trigger button is disabled if all possible condition are false, eg.:
<button mat-button [matMenuTriggerFor]="menu" [disable]="!condition1 && !condition2 && !condition3 && !conditionN">Menu</button>
<mat-menu #menu="matMenu">
<button mat-menu-item *ngIf="condition1">Item 1</button>
<button mat-menu-item *ngIf="condition2">Item 2</button>
<button mat-menu-item *ngIf="condition3">Item 3</button>
...
<button mat-menu-item *ngIf="conditionN">Item N</button>
</mat-menu>
There are a simple way for check if a MatMenu
has at least one MatMenuItem
and disable the trigger button if no one MatMenuItem
are available?
Solution
Issue with items
As mentioned in previous answer, one potential solution could be to use items
of exported matMenu
.
But we will have 2 issues :
items
property is deprecated, and could be removed soon.
/**
* List of the items inside of a menu.
* @deprecated
* @breaking-change 8.0.0
*/
items: QueryList<MatMenuItem>;
- set
disabled
property withmatMenu.items.length
will throw a NG0100 error if we are in default change detection strategy (not in OnPush), because change detection process is not finished.
Potential solution
To solve this, we can create a reusable directive, which will query MatMenuItem
of a MatMenu
, and then fire an event with the current status of menu : true
if at least one option, false
if not.
menu-toggled.directive.ts:
@Directive({
selector: 'mat-menu',
})
export class MenuToggledDirective implements AfterContentInit, OnDestroy {
_destroyed$ = new Subject<void>();
@ContentChildren(MatMenuItem, { descendants: true })
_items!: QueryList<MatMenuItem>;
@Output()
menuToggled = new EventEmitter<boolean>();
ngAfterContentInit(): void {
this._items.changes
.pipe(
takeUntil(this._destroyed$),
startWith(0),
map((_) => this._items.length > 0)
)
.subscribe(this.menuToggled);
}
ngOnDestroy(): void {
this._destroyed$.next();
this._destroyed$.complete();
}
}
Usage in app.component.html :
<button #button mat-stroked-button [mat-menu-trigger-for]="menu">
Menu
</button>
<mat-menu #menu="matMenu" (menuToggled)="button.disabled = !$event">
<button mat-menu-item *ngIf="flag">Item 1</button>
<button mat-menu-item *ngIf="false">Item 2</button>
</mat-menu>
Answered By - Thierry Falvo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.