[Fixed] How to create a formGroup to mark an option in the select field?

Issue

I have the following model that reflects the return of an API:

export class IScriptOperationsModel extends Serializable {
  public description: string;
  public descriptionCode: string;
  public scriptOperationOrders: IScriptOperationOrdersModel[];
}

export class IScriptOperationOrdersModel extends Serializable {
  public rank: number;
  public defaultTime: string;
  public asset?: IAssetModel;
  public provider?: IProviderModel;
}

export class IProviderModel extends Serializable {
  public id: number;
  public description: string;
}

export class IAssetModel extends Serializable {
  public id: number;
  public description: string;
}

my Class

operationModel: IScriptOperationsModel;
formOperation: FormGroup;
providers$: Observable<IResponse<IProviderModel>>;

constructor(private fb: FormBuilder, ...) {}

ngOnInit() {
  this.operationModel = new IScriptOperationsModel();
  this.operationModel.scriptOperationOrders = [];
  this.assetModel = new IAssetModel();
  this.providerModel = new IProviderModel();

  this.scriptOperationsService
  .findScriptOperation(this.operationId)
  .subscribe((operation) => {
    this.operationModel = operation.data as IScriptOperationsModel;
    const scriptOperationOrders = this.formOperation.get('scriptOperationOrders') as FormArray;
    this.operationModel.scriptOperationOrders.forEach((values) => {
      const createWorkstation = this.createWorkstation();
      createWorkstation.reset(values);
      scriptOperationOrders.push(createWorkstation);  // I populate the scriptOperationOrders
    })
    this.formOperation.setValue(this.operationModel);
  });
}

buildFormOperation() {
  this.formOperation = this.fb.group({
    descriptionCode: [],
    description: [null, Validators.required],
    scriptOperationOrders: this.fb.array([])
  })
}

createWorkstation(): FormGroup {
  return this.fb.group({
    rank: this.fb.control(''),
    defaultTime: this.fb.control('', Validators.required),
    asset:  this.fb.group( this.fb.control('')),          // doesn't work
    provider: this.fb.group( this.fb.control(''))         // doesn't work
  });
}

get scriptOperationOrders(): FormArray {
  return this.formOperation.get('scriptOperationOrders') as FormArray;
}

loadProviders() {
  this.providers$ = this.providerService.listProviders();
}

and my Template

<div class="card"
  formArrayName="workStations" 
  *ngFor="let workstation of formOperation.get('scriptOperationOrders')['controls']; index as idx"
>
 <div class="card-body" [formGroupName]="idx">
   <div class="form-row">
     <div class="form-group col-md-1">
       <label>Id Oper.</label>
         <input type="text" name="idOperation" class="form-control" formControlName="rank"/>
     </div>
     <div class="form-group col-md-2" formGroupName="provider">   <!-- I think it doesn't work -->
       <label>Provider</label>
       <select formControlName="id">           <!-- ERROR -->
         <option value="">Choose</option>
         <option 
           *ngFor="let prov of (providers$ | async)?.dataArray " 
           [value]="prov.id">{{ prov.description }}
         </option>
       </select>
     </div>
   </div>
 </div>
</div>

The form is filled in correctly, however, it gives an error in the console and so I am unable to mark the option with the option coming from the API.

enter image description here

enter image description here

How could I do to select an option on select when accessing the route?

Solution

I will post an answer, with the way I found to solve the problem. Basically I have seven values in the ngOnInit() method, so this way when I access the route provider, the fields that have data will be automatically filled with the respective API data.

What I needed to understand was that there was no need to create a formGroup for the asset and provider attributes

// ngOnInit()
this.scriptOperationsService
  .findScriptOperation(this.operationId)
  .subscribe((operation) => {
    this.operationModel = operation.data as IScriptOperationsModel;
    this.formOperation.patchValue({
      descriptionCode: this.operationModel.descriptionCode,
      description: this.operationModel.description,
    });
    this.operationModel.scriptOperationOrders.forEach(scriptOpOrder => {
      (this.formOperation.get('scriptOperationOrders') as FormArray).push(this.fb.group({
        rank: scriptOpOrder.rank,
        defaultTime: scriptOpOrder.defaultTime,
        asset: scriptOpOrder.asset?.id,         // Values needed to select the 
        provider: scriptOpOrder.provider?.id    // option based on the id
      }))
    })
  });

this.buildFormOperation();

buildFormOperation() {
  this.formOperation = this.fb.group({
    descriptionCode: [],
    description: [null, Validators.required],
    scriptOperationOrders: new FormArray([])
  })
}

enter image description here

Leave a Reply

(*) Required, Your email will not be published