LeAndrade
LeAndrade

Reputation: 138

How to handle two selects fields in a reactive Angular form?

I have a screen where I create elements dynamically using reactive form, basically I create cards, where each has two selection fields:

enter image description here

Scenario: when I add a card and select a layout, the options of that specific layout are loaded in the select of assets through a service that makes the filter in the API, however when I add another card and select some other option in the layout select the two selects of assets are left with the same option.

enter image description here

Template

<div class="card"
  formArrayName="scriptOperationOrders" 
  *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>Rank</label>
        <input type="text" name="rank" class="form-control" formControlName="rank"/>
      </div>
      <div class="form-group col-md-2">
        <label>Layout</label>
        <select formGroupName="layout" (ngModelChange)="searchAssetsByLayouts($event)">
          <option value="">Choose Layout</option>
          <option 
            *ngFor="let lay of (layouts$ | async)?.dataArray " 
            [value]="lay.id">{{ lay.description }}
          </option>
        </select>
      </div>
      <div class="form-group col-md-2">
        <label>Asset</label>
        <select formGroupName="asset">
          <option value="">Choose Asset</option>
          <option 
            *ngFor="let asset of (assets$ | async)?.dataArray " 
            [value]="asset.id">{{ asset.description }}
          </option>
        </select>
      </div>
    </div>
  </div>
</div>

Controller

layouts$: Observable<IResponse<ILayoutModel>>;
assets$: Observable<IResponse<IAssetModel>>;

ngOnInit() {
  ...
  this.buildFormOperation();
  this.layouts$ = this.layoutService.listLayouts();
  this.providers$ = this.providerService.listProviders();
}

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

searchAssetsByLayouts(layoutId: number) {
  this.assets$ = this.assetService.listAssetsRoots(layoutId); // The assets$ variable is overridden here
}

Asset listing Service

listAssetsRoots(layoutId?: number | string): Observable<IResponse<IAssetModel>> {
  return this.apiService.crudeList({
    url: `${this.url}/roots`,
    queryParams: {
      layoutId
    },
  })
  .pipe(map((res) => {
    return new IResponse<IAssetModel>(res, IAssetModel);
  }));
}

As you could be doing when selecting an option in the select layout, the options for that layout are loaded only in the select of assets on the same card

Upvotes: 0

Views: 93

Answers (1)

Sandeep Modak
Sandeep Modak

Reputation: 842

this.assets$ = this.assetService.listAssetsRoots(layoutId); as The assets$ variable is overridden here
ts file:-

//declared what type of response is expected 
interface Assets{
  id:number,
  description :string
}
//initially set to empty
assets$ : Observable<Assets[]> = of([]);


//accepting second argument idx as row_index
 
 searchAssetsByLayouts(layoutId: number,row_index:number) {
  this.assets$[row_index] = this.assetService.listAssetsRoots(layoutId); // The assets$ variable is no more overridden
}

//html:-
//here used formControlName for 'layout' and 'asset' control insted of formGroupName
//and passed 'idx' as second parameter  to (ngModelChange)="searchAssetsByLayouts($event,idx)

<div class="card"
  formArrayName="scriptOperationOrders" 
  *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>Rank</label>
        <input type="text" name="rank" class="form-control" formControlName="rank"/>
      </div>
      <div class="form-group col-md-2">
        <label>Layout</label>
        <select formControlName="layout" (ngModelChange)="searchAssetsByLayouts($event,idx)">
          <option value="">Choose Layout</option>
          <option 
            *ngFor="let lay of (layouts$ | async)?.dataArray " 
            [value]="lay.id">{{ lay.description }}
          </option>
        </select>
      </div>
      <div class="form-group col-md-2">
        <label>Asset</label>
           <select formControlName="asset">
                  <option value="">Choose Asset</option>
                  <option 
                    *ngFor="let asset of (assets$[idx] | async)" 
                    [value]="asset.id">{{ asset.description }}
                  </option>
         </select>
      </div>
    </div>
  </div>
</div>

Upvotes: 1

Related Questions