How to make a 'mat-select' readonly?
Asked Answered
C

6

28

I am working on a angular 5 project. There are many mat-select elements which is supposed to be readonly like text boxes. I found out that there is a disabled feature which is:

  <mat-form-field>
    <mat-select placeholder="Choose an option" [disabled]="disableSelect.value">
      <mat-option value="option1">Option 1</mat-option>
      <mat-option value="option2" disabled>Option 2 (disabled)</mat-option>
      <mat-option value="option3">Option 3</mat-option>
    </mat-select>
  </mat-form-field>

which out put looks like:

enter image description here

It fades out the text and the lining below get changes, is it possible to make it readonly?

Classicize answered 26/6, 2018 at 6:5 Comment(4)
No, not in the most common way, since it's mimicking the native select selector in HTML. [That has no attribute either of readonly][1]. [1]: developer.mozilla.org/en-US/docs/Web/HTML/Element/selectConvertite
then something that can just disable the dropdown.Classicize
Tried CSS for disabling pointers?Laggard
The solution with panelClass worked for mePreferential
L
23

Add CSS to both select block and mat-form-field block, these can be applied automatically to all the select elements:

<mat-form-field class="readonly-wrapper">
  <mat-select class="readonly-block" placeholder="Choose an option" [disabled]="disableSelect.value">
    <mat-option value="option1">Option 1</mat-option>
    <mat-option value="option2" disabled>Option 2 (disabled)</mat-option>
    <mat-option value="option3">Option 3</mat-option>
  </mat-select>
</mat-form-field>  

CSS code:

.readonly-wrapper {
    cursor: not-allowed;
}

.readonly-wrapper .readonly-block {
    pointer-events: none;
}
Laggard answered 26/6, 2018 at 8:9 Comment(1)
this does not prevent the element to get focused and select options with keyboardBushing
L
19

You can combine an editable select with a readonly textbox and ngIf between them:

  <mat-form-field>
    <mat-label>Choose an option</mat-label>
    <input *ngIf="!editing" mat-input formControlName="mySelect" [readonly]="true">
    <mat-select *ngIf="editing" formControlName="mySelect">
      <mat-option value="option1">Option 1</mat-option>
      <mat-option value="option2" disabled>Option 2 (disabled)</mat-option>
      <mat-option value="option3">Option 3</mat-option>
    </mat-select>
  </mat-form-field>
Lexine answered 9/8, 2019 at 13:39 Comment(1)
Except your textbox would show "option1" and not "Option 1"Middlebreaker
C
3

You can replace the mat-select form field with a input box and bind input box data with mat-select data.

Canonist answered 28/6, 2021 at 6:20 Comment(0)
A
1

Actually you can use panelClass to hide options dropdown in readonly mode:

.hidden { display: none; }
<mat-select [panelClass]="readonly ? 'hidden' : ''"></mat-select>
Adductor answered 4/1, 2023 at 7:53 Comment(0)
M
1

If there are a small number of inputs you require this for, I would recommend a different approach.

Swap out the select for a readonly input, and restore the select when required. You can do this by togging a boolean property (in the examples below, this property is called isReadMode) The primary benefit of doing it this way is avoiding cross-platform / browser incompatibility of CSS and/or device events, as you'd be leaving that to Angular/HTML to handle appropriately.

You can add an icon and style it to look like a select, but in my experience, it's sufficient to simply use a readonly input "as is".

Documentation for input with an icon can be found here.
Angular pre-17 example without an icon:

<mat-form-field>
    <mat-label>Choose an option</mat-label>
    <ng-container *ngIf="isReadMode; else interactiveSelectTemplate">
        <!-- Can use NG Model as well or simply double curly braces. -->
        <input matInput readonly [value]="form.get('yourFormField')?.value">
    </ng-container>

    <ng-template #interactiveSelectTemplate>
        <mat-select formControlName="yourFormField">
            <mat-option **ngFor="let opt of options" [value]="opt.value">{{opt.display}}</mat-option>
        </mat-select>
    </ng-template>
</mat-form-field>

Documentation for Angular 17+ control flow (use of @if) can be found here.
Angular 17+ example with an icon:

<mat-form-field>
    <mat-label>Choose an option</mat-label>
    @if (isReadMode) {
        <!-- Can use NG Model as well or simply double curly braces. -->
    <input matInput readonly [value]="form.get('yourFormField')?.value">
    } @else {
    <mat-select formControlName="yourFormField">
        @for (opt of options; track opt.value) {
        <mat-option [value]="opt.value">{{opt.display}}</mat-option>
        }
    </mat-select>
    }
    <mat-icon *ngIf="isReadMode" matSuffix>arrow_drop_down</mat-icon>
</mat-form-field>

Note: In Angular 17+ the carrot down icon is in the same scope as the mat-form-field and with its own *ngIf. This can be adjusted where the @if/@else contains a whole <mat-form-field> to include the icon within the @if condition at the cost of lengthy code.

If there are many fields, it may be best to create a wrapper component to reduce the duplicate code or to use one of the other solutions proposed.

Mohl answered 3/4, 2024 at 11:29 Comment(0)
R
0

Today is 2023-11-09. I'm using Angular v16, regular <select>. Neither [attr.readonly], nor [attr.disabled], nor [disabled] work.

Solution is

  • .css .disabledsel {pointer-events: none;}
  • html [ngClass]="{'disabledsel': condition}"
Rodd answered 9/11, 2023 at 21:15 Comment(2)
and you get the value from this select, because i can'tConvince
It simply cancels the pointer event.Rodd

© 2022 - 2025 — McMap. All rights reserved.