8

When <mat-menu> is used on <mat-form-field> it takes the focus from the input. I want the user to be able to use the input while the menu is opened.

Is this possible?

<mat-form-field appearance="outline" [matMenuTriggerFor]="appMenu">
  <mat-label>Label color</mat-label>
  <div class="color-container">
    <div class="color-dot" [style.backgroundColor]="label.color"></div>
  </div>
  <input #input matInput class="pl-2" [(ngModel)]="label.color">
</mat-form-field>


<mat-menu #appMenu="matMenu" yPosition="below" [overlapTrigger]="false">
  <mat-grid-list cols="8" rowHeight="30px">
    <mat-grid-tile *ngFor="let color of colors">
      <div mat-menu-item class="menu-item">
        <div class="color-dot" [style.backgroundColor]="color" 
                               (click)="label.color = color"></div>
      </div>
    </mat-grid-tile>
  </mat-grid-list>
</mat-menu>

stackblitz example

1
  • 1
    I think Luca De Nardi answered this below. It works for me. Commented Jun 6, 2019 at 17:58

4 Answers 4

14

You can easily achieve this by adding

<mat-menu #myMenu="matMenu">
    <form (click)="stopPropagation($event)">
        <!-- Your content and inputs -->
    </form>
</mat-menu>

And in your component

stopPropagation(event){
    event.stopPropagation();
}

This will prevent the event propagation, so the button that opens the menu won't receive the "toggle" trigger.

EDIT: As Jakub said in the comments, you can also skip the function creation and immediately call the stopPropagation method from the template with

  <form (click)="$event.stopPropagation()">
4
  • 1
    Excellent. In my case, I was using mat-menu-item and i was able to put (click)="stopPropagation($event)" on there (instead of in <form>). Thanks. Commented Jun 6, 2019 at 17:56
  • 4
    Why do you create the stopPropagation function? Just call (click)="$event.stopPropagation()" .... It's better to create less dependencies than more ....
    – Jakub
    Commented Dec 22, 2020 at 13:04
  • @Jakub you're correct, I'll update the answer. I've done this some time ago, and if I had to do it now I'd do as you advise :) Commented Dec 23, 2020 at 11:09
  • I think you didn't understand the question, you should be able to edit the text of the input while the menu is open. Commented Jun 3, 2022 at 16:24
1

As far as I understood you want your inputs outside the mat-menu, in lower level, while having the mat menu open with different color options as reference. If that's not the case, you should put the mat-form-field tag inside mat-menu tag, as pointed above. Only thing is I don't understand why then you have to prevent the mat-menu from closing on focusing on the inputs, 'cause that has never happens to me, only with tab key which closes the menu if you have inputs inside it, on that case you have to catch the keydown event and prevent it, with the problem of preventing also ESC key... But If what you want is the menu to be open and be able to write on your inputs on a lower level at the same time, what you have to do is to disable backdrop for your mat-menu. That you can make it on the html like this:

<mat-menu #myMenu="matMenu" [hasBackdrop]="false"></mat-menu>
1
  • This is close, but still, the focus is taken away by the popup menu Commented Jun 3, 2022 at 16:27
0

If you want to enter text while the menu is open and assuming you open the menu with a click on the color item (add a cursor pointer on it) - you need to move the 'matMenuTriggerFor' to a lower level element:

<div class="color-container" [matMenuTriggerFor]="appMenu">
    <div class="color-dot" [style.backgroundColor]="label.color"></div>
</div>

If you still want it to be on the top level - its a lot more difficult (you will need to start allow and block events on internal levels).

6
  • I want the menu to open but I don't want it to close! I just want to be able to enter text while the menu is open Commented Aug 2, 2018 at 6:30
  • Edited - i hope its what you asked. Commented Aug 2, 2018 at 7:54
  • Nope! did you try your change in the stackblitz.com/edit/…? Commented Aug 4, 2018 at 6:24
  • Yes, and it works. You cannot put your trigger on the top element which is a wrapper for both parts of your code. It seems that you changed your code now so my answer was based on your previous code. Commented Aug 4, 2018 at 6:36
  • No, I did not change anything and it is not a wrapper issue!!! the menu doesn't allow any other action while it is open. BTW why don't you fork that stackblitz update it with your changes then add it to your answer? Commented Aug 4, 2018 at 6:41
0

A small walkaround if you have a input inside mat-menu and want to search a list using pipe.

<form (click)="$event.stopPropagation($event)">
        <input
          class="w-full border-b"
          #search
          (input)="inputEvent()"
          [(ngModel)]="query"
          [ngModelOptions]="{ standalone: true }"
          type="text"
        />

@ViewChild('search') search: ElementRef;

public inputEvent = () => setTimeout(() => this.search.nativeElement.focus(), 200);

Not the answer you're looking for? Browse other questions tagged or ask your own question.