Search code examples
angularmaterial-uidropdownmat-select

How to add a button in a mat-select option when an option is selected?


I'm trying to add a url button next to an mat-select option when it is selected. Clicking that button will open a new tab with info related to that option. I don't want all options to have this button when the mat-select is dropped down, just when it is selected.

With the code below, the links appear in the dropdown and is clickable, but when an option is selected, the button is not clickable and just displays the text 'Open', no button visible.

I'm having trouble finding a solution for this. Does anyone how I can accomplish this?

<mat-select [formControl]="formControl" (optionSelected)="onSelected($event)">
       <mat-option></mat-option>
       @for (option of options; track option) {
           <mat-option [value]="option.value">
             {{option.key}}
             <button (click)="openLink()">Open<button> <!-- only want this when it is selected -->
           </mat-option>
       }
</mat-select>

Solution

  • NOTE: If the option is not already selected, when you open a drop-down and select an option, the drop-down will close immediately. As a result even if you add the button next to selected mat-option, the button will be invisible along with the mat-option.

    You can see and interact with the button, only if the option was previously selected.

    You mention that's your requirement:

    Unfortunately, my requirement is to have the button within the selected option.

    Here is the code:

    <mat-select
      #my_select
      [formControl]="formControl"
      (optionSelected)="onSelected($event)">
          <mat-option></mat-option>
          @for (option of options; track option) {
              <mat-option [value]="option.value">
                {{option.key}}
              @if(my_select.value === option.value){
                <button (click)="openLink()">Open<button>
              }
              </mat-option>
          }
    </mat-select>
    
    

    Explanation:
    The above code uses a variable, #my_select to refer the mat-select, there are many other ways to refer to the element/component, and I chose this method.

    You can declare a variable on an element in a template by adding an attribute that starts with the hash character (#) followed by the variable name.

    reference

    Then, using @if to compare values of the selected option and the mat-option value, if they are the same, the code is displaying the button.

    If you want to keep the options drop-down open even after the selection, then you should get the reference to the mat-select in your class and call its open method when selectionChange event fires.

    UPDATE

    The button isn't click. It just displays the text of the mat-icon. Is there a way to turn that text into an actual html button element?

    To solve this issue, you can stop the event propagation when the button is clicked. This way, the button click will fire its intended method without triggering the selection of the mat-option.

    On your template pass the event object to the openLink method.

    <mat-select
      #my_select
      [formControl]="formControl"
      (optionSelected)="onSelected($event)">
          <mat-option></mat-option>
          @for (option of options; track option) {
              <mat-option [value]="option.value">
                {{option.key}}
              @if(my_select.value === option.value){
                <button (click)="openLink($event)">Open<button>
              }
              </mat-option>
          }
    </mat-select>
    
    

    On your component class prevent the click event from bubbling up to the mat-option.

    
    openLink(event: MouseEvent): void {
        event.stopPropagation(); // Prevent the click event from bubbling up
      
        // Your custom logic here
      }