angularselectangular-material

Angular material select json value to show only the specific value with keyvalue


I want to show the value sent as json in the backend, and only the waterType value that comes with the json value with angular material select. Here, when the angular select is run with keyvalue, all json values ​​come. How can I filter these values ​​so that only waterType is selected?

enter image description here

json

{
  "waters": [
    {
      "id": "f657db7a-9f0a-40b3-9af7-e9c7b1e02df7",
      "conductance": 900,
      "conductanceMax": 1300,
      "createdDate": "2024-08-10T01:45:36.1906201",
      "updatedDate": "0001-01-01T00:00:00",
      "waterType": "xxxxx"
    },
}

WaterService

export class WaterServiceService {

  constructor(private httpclient: HttpClient) {

  }


  getWaters(): Observable<List_Water_Type[]> {
    return this.httpclient.get<List_Water_Type[]>('https://localhost:7131/api/Water/')
  }

createComponent:

  private loadWaters(){
    this.waterService.getWaters().subscribe(data=>{this.waters=data})
  }

html:

<div class="form-details">
  <div *ngFor="let ot of waters | keyvalue">
    <ng-container >
      <mat-form-field>
        <mat-label>Water</mat-label>
        <mat-select formControlName="water" [(ngModel)]="selectedWater" >
          <mat-option  *ngFor="let water of waters[ot.key] | keyvalue" [value]="water.key" >
            {{water.value | json}}
          </mat-option>
        </mat-select>
      </mat-form-field>
    </ng-container>
  </div>
</div>

Solution

  • You are mixing angular reactive forms (formControlName) and angular template driven forms (ngModel) which is a bad idea, you have to choose between either of the two. Learn more in angular.dev.

    Second issue is the HTML is too complicated, you just need to set the array to the select and it will render without any issues.

    <div class="form-details">
      <mat-form-field>
        <mat-label>Water</mat-label>
        <mat-select [(ngModel)]="selectedWater">
          <mat-option *ngFor="let water of waters" [value]="water.id">
            <!-- changed here! -->
            {{water?.waterType}}
            <!-- changed here! -->
          </mat-option>
        </mat-select>
      </mat-form-field>
    </div>
    

    We also need to create interfaces for the API response as well as the waters array.

    Service:

    import { HttpClient } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import { Observable, of } from 'rxjs';
    import { List_Water_Type } from 'src/example/select-overview-example';
    
    export interface WatersResponse {
      waters: List_Water_Type[];
    }
    
    @Injectable({
      providedIn: 'root',
    })
    export class WatersService {
      constructor(private httpclient: HttpClient) {}
    
      getWaters(): Observable<WatersResponse> {
        return of({
          waters: [
            {
              id: 'f657db7a-9f0a-40b3-9af7-e9c7b1e02df7',
              conductance: 900,
              conductanceMax: 1300,
              createdDate: '2024-08-10T01:45:36.1906201',
              updatedDate: '0001-01-01T00:00:00',
              waterType: 'xxxxx',
            },
          ],
        }) as Observable<WatersResponse>;
      }
    }
    

    Component TS:

    import { Component, inject } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { MatInputModule } from '@angular/material/input';
    import { MatSelectModule } from '@angular/material/select';
    import { MatFormFieldModule } from '@angular/material/form-field';
    import { CommonModule } from '@angular/common';
    import { WatersResponse, WatersService } from 'src/app/waters.service';
    
    export interface List_Water_Type {
      id: string;
      waterType: string;
      conductance: number;
      conductanceMax: number;
      createdDate: Date | string;
      updatedDate: Date | string;
    }
    
    /**
     * @title Basic select
     */
    @Component({
      selector: 'select-overview-example',
      templateUrl: 'select-overview-example.html',
      standalone: true,
      imports: [
        MatFormFieldModule,
        MatSelectModule,
        MatInputModule,
        FormsModule,
        CommonModule,
      ],
    })
    export class SelectOverviewExample {
      waterService = inject(WatersService);
      selectedWater = '';
      waters: List_Water_Type[];
    
      ngOnInit() {
        this.loadWaters();
      }
    
      private loadWaters() {
        this.waterService.getWaters().subscribe((data: WatersResponse) => {
          this.waters = data.waters;
        });
      }
    }
    

    Stackblitz Demo