Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use mat-select-trigger with *ngFor

mat-option has *ngFor and I am displaying {{some text}} and an icon in there so, on selecting any one of the options both the {{some text}} and icon text is getting displayed in mat-form-field. ex: if I have a text "bbnh" and info icon. On selecting this option I want it to display just "bbnh" image_for_the_above

I tried *ngFor on mat-select-trigger as in mat-options but it's not working.

    <mat-form-field>
      <mat-select  placeholder="Select offer" formControlName="promo">
        <mat-select-trigger>
          {{ item.promo_code }} //Error occuring in this line
        </mat-select-trigger>
        <mat-option *ngFor="let item of promotions" [value]="item"
          >{{ item.promo_code }}
          <i class="material-icons">
            info
          </i>
        </mat-option>
      </mat-select>
    </mat-form-field>

Identifier 'item' is not defined. The component declaration, template variable declarations, and element references do not contain such a

like image 497
Bharath Bhushan Avatar asked May 21 '19 05:05

Bharath Bhushan


2 Answers

From what i have understood i guess this is what you are looking for

<mat-form-field>
  <mat-select  placeholder="Select offer" formControlName="promo" [(value)]="selected">
    <mat-select-trigger>{{selected}}</mat-select-trigger>
    <mat-option *ngFor="let item of promotions" [value]="item"
      >{{ item.promo_code }}
      <i class="material-icons">
        info
      </i>
    </mat-option>
  </mat-select>
</mat-form-field>

this should work! If you are facing any errors let us know in the comments

like image 86
Thivagar Avatar answered Sep 17 '22 10:09

Thivagar


This is the suggested way of doing it in the sample code:

<mat-form-field appearance="fill">
  <mat-label>Toppings</mat-label>
  <mat-select [formControl]="toppings" multiple>
    <mat-select-trigger>
      {{toppings.value ? toppings.value[0] : ''}}
      <span *ngIf="toppings.value?.length > 1" class="example-additional-selection">
        (+{{toppings.value.length - 1}} {{toppings.value?.length === 2 ? 'other' : 'others'}})
      </span>
    </mat-select-trigger>
    <mat-option *ngFor="let topping of toppingList" [value]="topping">{{topping}}</mat-option>
  </mat-select>
</mat-form-field>

In this example the current form value for toppings (which is a string array) is used to display a list of selected toppings (it's basically doing the equivalent of toppings.join(' + '). This only works nicely here because all information needed is present in the form value itself.

Often when I have a select the information I want to display in the select is NOT all stored in the form control value. Either because the form value is not humanly readable (perhaps it contains "PEP" instead of "Pepperoni") or because I want to display something else like number of calories or an image.

One brute force solution is to just iterate through the list again inside your mat-select-trigger and display the value when you find the matching topping. This seems clumsy but is often the best solution I've found.

Note I've tweaked the model slightly from the Angular example code. I am iterating through an object { id: string, name: string, calories: number, surcharge: number } and not a simple array of strings and I also changed the selected form value from an array of toppings to the id of a single topping.

    <mat-select-trigger>

        <ng-container *ngFor="let t of pizzaToppings">
            <ng-container *ngIf="topping.value == t.id">

                {{ t.name }} ({{ t.calories }}) ({{ t.surcharge | currency }})
            </ng-container>
        </ng-container>

    </mat-select-trigger>

So this is simply duplicating what you already have inside the mat-option *ngFor. You can offload some of this to an ng-template but then you won't get all the auto completion.

There's a negligible performance impact, it's just a bit ugly - but I rarely need to display the actual form value in the mat-select-trigger and this is the best way I found.

I really feel like this is an area where the framework could be improved - but I'm not sure how that would work.

like image 23
Simon_Weaver Avatar answered Sep 18 '22 10:09

Simon_Weaver