Unable to set value of select option to first element in ngFor loop with Angular Reactive Forms

42 Views Asked by At

I have a select input with an ngFor loop in it to create the options based on colors array.

The behavior i need is to automatically select the first option and to so that angular reactive forms can get its value when the input is created/changed.

So far my form, it looks like this :

<form [formGroup]="stepOneForm">
  <label for="modelSelect">Model:</label>
  <select id="modelSelect" formControlName="model">
    <option value="" selected>Choose...</option>
    <option *ngFor="let model of models" [value]="model.code">
      {{ model.description }}
    </option>
  </select>

  <!-- The input i am interested in -->
  <ng-container *ngIf="stepOneForm.get('model')?.value as code">
    <label for="colorSelect">Color:</label>
    <select id="colorSelect" formControlName="color" (change)="onColorSelected()" [value]="colors[0].code">
      <option *ngFor="let color of colors" [value]="color.code">
        {{ color.description }}
      </option>
    </select>
    <img [src]="imagePath" alt="car">
  </ng-container>
</form>

And my TS part looks like this :

ngOnInit() {
    this.carService.getModels().subscribe(models => {
      this.models = models;
    });

    this.stepOneForm.valueChanges.subscribe(() => {
      this.carService.updateStepOneValidity(this.stepOneForm.valid);
      const model = this.stepOneForm.get('model')?.value
      this.colors = this.models.find(modelObj => modelObj.code === model)?.colors ?? [];
      
      console.log(this.stepOneForm.get('color')?.value) // This returns '' (empty string)
      
      if (model) {
        this.carService.updateShoppingCart(this.stepOneForm.value)
      }
    })
  }

When the ng-container content gets displayed, the subscription gets triggered and on the color input I see a color selected by default, but on this line I get an empty string while i should get the value of this option :

console.log(this.stepOneForm.get('color')?.value)

1

There are 1 best solutions below

0
traynor On BEST ANSWER

It's only updating the view, but to update color form control value programmatically when updating model form control, it has to be done with form methods, from the component, with .setValue/.patchValue.

So, you could add a listener to the first select, and then update color form control.

<select id="modelSelect" formControlName="model" (change)="onModelSelected()">
  onModelSelected() {
    this.stepOneForm.get('color').setValue(this.colors[0]?.code || '');
  }

You could do it from the existing valueChanges by adding {emitEvent: false}, to prevent infinite loop, but then the colors select wouldn't work, so you need to do it from the first select, i.e. you need extra listener.