Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Material: CheckBox in mat-menu; Problem with dark themes

You can't put a <mat-checkbox> in a <mat-menu> normally. If so, dark themes don't apply to the text-part of your <mat-checkbox> (see the image at the end).

About <mat-label>s there is a similar issue. But the solution is simple:

  • Using <label mat-menu-item> instead of <mat-label>.

Similarly about buttons.


But I couldn't find a similar solution for <mat-checkbox>es! These are all states that I tested:

<mat-menu #menu="matMenu">
  <mat-label>Bad label</mat-label>
  <label mat-menu-item>OK label</label>
  <mat-checkbox>Problem here</mat-checkbox>
  <!-- ERROR:
  <mat-checkbox  mat-menu-item>
    Template parse errors:
More than one component matched on this element.
  </mat-checkbox>
  -->
  <br><mat-checkbox></mat-checkbox>
  <label mat-menu-item style="display:inline">Not good workaround</label>
</mat-menu>

stackblitz

And the result:

enter image description here

like image 879
Mir-Ismaili Avatar asked Mar 07 '19 22:03

Mir-Ismaili


3 Answers

There appears to be a way to assign menuitemcheckbox to the role input, on the mat-menu-item directive... unfortunately, I am not clear on how it should work...

<!-- https://github.com/angular/material2/commit/3f1588f562a4abd85d6add87a4f6ed969ba56898#diff-4cc67949abfd84b09e8b7178ac357febR2134 -->
  <button mat-menu-item role="menuitemcheckbox" aria-checked="true">Checked</button>
  <button mat-menu-item role="menuitemcheckbox" aria-checked="false">Not </button>

With that being said, assigning the mat-menu-item class rather than the directive may be a viable workaround.

<mat-checkbox class="mat-menu-item">Problem here</mat-checkbox>  

Stackblitz

https://stackblitz.com/edit/angular-j4ftuc-5s5k3t?embed=1&file=app/menu-overview-example.html

like image 106
Marshal Avatar answered Nov 04 '22 17:11

Marshal


Since Angular Material 11 the class="mat-menu-item" Workaround introduced by Marshal seems to be broken. You can fix it by applying the mat-menu-item directive on a div wrapping your mat-checkbox.

<div mat-menu-item>
  <mat-checkbox>Problem here</mat-checkbox> 
</div>

Be aware that the checkbox is now only triggered when you click exactly on the checkbox, not when you press any other spot of the menu-item. This causes only a click animation. To workaround this you can register a (click)="..." listener on the wrapping div.

like image 34
Aki Avatar answered Nov 04 '22 16:11

Aki


Elaborating on Aki's answer:

<div mat-menu-item (click)="$event.stopPropagation(); cb.toggle()" (keydown.enter)="$event.stopPropagation(); cb.toggle()">
  <mat-checkbox class="mat-menu__checkbox" (click)="$event.stopPropagation()" #cb>Problem No Longer Here</mat-checkbox>
</div>

The wrapper div needs (keydown.enter) so the keyboard controls for the mat menu will still work correctly. We also register a click event so if the user clicks on the right or left edges of the menu item it will toggle the checkbox. $event.stopPropagation() is here to prevent the menu from closing while the user is interacting with the checkboxes.

Then add the following to your style sheet:

.mat-menu__checkbox {
  height: 100%;
  &::ng-deep .mat-checkbox-layout {
    height: 100%;
    &::ng-deep .mat-checkbox-label {
      margin: auto;
      vertical-align: middle;
      position: relative;
    }
  }
}

This style will make the label of your mat checkbox the full height of the menu item and keep it vertically centered. This makes it so the checkbox can be clicked anywhere and it will trigger.

like image 2
emassie Avatar answered Nov 04 '22 17:11

emassie