Angular 11 selected default value of mat-select populated with observable

1.1k views Asked by At

I have a module ProgettiAzioniModule shared between two components SchedarioComponent and SituazioneClienteComponent. This module consist of two mat-select:

<div class="progettiAzioniBody">
    <div>
        <h3 class="progettiAzioniTitle">
            {{ 'anms.progettiazioni.selezionaprogettoazione' | translate}}
        </h3>
    </div>
    <div fxLayout fxLayoutGap="10px" fxLayout.xs="column">
        <mat-form-field *ngIf="progetti$ | async" appearance="outline">
            <mat-select [(value)]="selectedIdProgetto" ngModel [formControl]="prjSearchCtrl" placeholder="{{ 'anms.progettiazioni.selezionaprogetto' | translate}}" name="progetto" required (selectionChange)="onProjectChange($event)" #singleSelect>
                <mat-option>
                    <ngx-mat-select-search [formControl]="prjSearchFilterCtrl" noEntriesFoundLabel="{{ 'anms.shared.nessunrisultato' | translate}}" placeholderLabel="{{ 'anms.shared.cerca' | translate}}"></ngx-mat-select-search>
                </mat-option>
                <mat-option *ngFor="let progetto of prjFilteredSearch | async" [value]="progetto.IDProgetto">                    
                    {{ progetto.NomeEsterno }}
                </mat-option>
            </mat-select>
        </mat-form-field>       
        <mat-form-field appearance="outline">
            <mat-select [(value)]="selectedIdAzione" ngModel placeholder="{{ 'anms.progettiazioni.selezionaazione' | translate}}" name="azione" required (selectionChange)="onActionChange($event)">
                <mat-option *ngFor="let azione of azioni$ | async" [value]="azione.IDAzione">
                    {{ azione.DescrizioneAzione }}
                </mat-option>
            </mat-select>
        </mat-form-field>
    </div>
</div> 

In SchedarioComponent I select project and action from mat-select and I pass these two values through parameters of a router.navigate to SituazioneClienteComponent

situazioneCliente(anagrafica: AnagraficheSchedario) {
    const myurl = `/situazione-cliente/${anagrafica.IDAnagrafica}/${this.idProgetto}/${this.idAzione}`;
    this.router.navigateByUrl(myurl);

  }

In SituazioneClienteComponent I set two @Output number variable with values from router parameters:

@Output() selectedIdProgetto: number;
@Output() selectedIdAzione: number;

constructor(private store: Store,private actRoute: ActivatedRoute) {
    this.idAnagrafica = this.actRoute.snapshot.params.idAnagrafica;
    this.selectedIdProgetto = this.actRoute.snapshot.params.idProgetto;
    this.selectedIdAzione = this.actRoute.snapshot.params.idAzione;
  }

ProgettiAzioniComponent receives this two variables in @Input. So, from SitazioneClienteComponent I can pass these variables to the selector of ProgettiAzioniComponent through [selectedIdProgetto] and [selectedIdAzione]

<div class="situazioneClienteBody">

    <div fxLayout fxLayout.xs="column">
        <div class="infoAnag">
            {{idAnagrafica}}
        </div>
        <div class="azioniAnag">
            <div class="schedarioProgettiAzioni">
                <anms-progettiazioni [azioni$]="azioni$" [progetti$]="progetti$" [selectedIdProgetto]="selectedIdProgetto" [sele
    ctedIdAzione]="selectedIdAzione" (prgEvent)="progettoFromChild($event)" (actEvent)="azioneFromChild($event)">
                </anms-progettiazioni>
            </div>
        </div>
    </div>
</div>

I can see these value in ProgettiAzioniComponent, but I'm not able to preselect the mat-select option with them, even if I set the [(value)] of the two mat-select like [(value)]="selectedIdProgetto" and [(value)]="selectedIdAzione"

Could someone help me? Thanks in advance

2

There are 2 answers

2
AudioBubble On

Do not use value but ngModel here

<mat-select [(ngModel)]="selectedIdProgetto" ...

<mat-select [(ngModel)]="selectedIdAzione" ...

Just to show you my minimal project.

HTML

<div class="progettiAzioniBody">
  <div>
    <h3 class="progettiAzioniTitle">
      anms.progettiazioni.selezionaprogettoazione
    </h3>
  </div>
  <div>
    <mat-form-field appearance="outline">
      <mat-select [(ngModel)]="selectedIdProgetto" [formControl]="prjSearchCtrl"
                  placeholder="xyz"
                  required (selectionChange)="onProjectChange($event)"
                  #singleSelect>
        <mat-option value="Default">Default</mat-option>
        <mat-option *ngFor="let title of titles" [value]="title">
          {{ title }}
        </mat-option>
      </mat-select>
    </mat-form-field>
  </div>

  <input type="text" 
   placeholder="Enter a title"  
   [(ngModel)]="selectedIdProgetto">
</div>

TS

  titles = ['A', 'B', 'C', 'D'];
  selectedIdProgetto: any;
  prjSearchCtrl: FormControl = new FormControl();


  onProjectChange(selection: MatSelectChange) {
    this.selectedIdProgetto = selection.value;
  }

AppModule

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    FormsModule,
    BrowserModule,
    MatFormFieldModule,
    MatSelectModule,
    BrowserAnimationsModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
0
Wayne Yan On

Do not have an answer (CORRECTED BELOW), but experiencing the same problem with Observable<T[]> and the operative difference between the working example and the answer provided by user6749601 is the use of a simple array vs an observable. Notice the difference between :

<mat-option *ngFor="let title of titles" [value]="title">

and the piped async observables in

<mat-option *ngFor="let azione of azioni$ | async" [value]="azione.IDAzione">

binding [(ngModel)] on the select does not seem to work for model to view given async conditions.

Correction : This cause of this issue is found! Yay! ... the select is using object identity as opposed to some sort of equals() implementation. If you instantiate a new object and use it as a model to view binding. Then it will (on object identity) not necessarily be "equal" to the values backing the select list. Hence the select list will not select the initalized model value. Provide a comparator function. This original angular documentation explains the WHY ...

https://angular.io/api/forms/SelectControlValueAccessor#customizing-option-selection