Search code examples
javascriptangulartypescriptangular-reactive-formsformarray

select option independent in formArray Angular


Good evening, I have a problem I am using a reactive form, with FormArray, I have a button to add 2 options as many times as necessary, the problem is that the options are matselects and in one of these selects I use an event (change), the problem is that adding the options for the first time the onchange works normal, but when adding the options more than 2 times the values that were previously selected in the matselects change because the onchange of the created select is re-executed. I would like to know if there is a way to use that event independently in each iteration of the formArray

Component.ts

alicuotaForm: FormGroup;
  value = this.fb.group({
    manzana: ['', Validators.required],
    villa: ['', Validators.required],
  });
  nregistros: number;

 ngOnInit() {
    this.alicuotaForm = this.fb.group({
      times: this.fb.array([]),
    });
  }

//event onchange
  getVillas(value) {
    console.log('valor: ', value.value);
    this.filtro = this.villas.filter((x) => x.manzana == value.value);
  }
  addGroup() {
    const val = this.fb.group({
      manzana: ['', Validators.required],
      villa: ['', Validators.required],
    });
    const alicuotaForm = this.alicuotaForm.get('times') as FormArray;
    alicuotaForm.push(val);
    this.nregistros = alicuotaForm.length;
  }

  removeGroup(index) {
    const alicuotaForm = this.alicuotaForm.get('times') as FormArray;
    alicuotaForm.removeAt(index);
  }

  trackByFn(index: any, item: any) {
    return index;
  }

component.html

<div class="container">
  <div class="row">
    <div class="col-col-6">
      <label class="transparente"></label>
      <button (click)="addGroup()" type="button" class="btn btn-success">
        Agregar Campos
      </button>
    </div>
    <br />
    <form [formGroup]="alicuotaForm">
      <ng-container
        formArrayName="times"
        *ngFor="
          let time of alicuotaForm.controls.times?.value;
          let i = index;
          trackBy: trackByFn
        "
      >
        <ng-container [formGroupName]="i" style="margin-bottom: 10px;">
          Iteracion {{ i + 1 }}
          <div class="col-col-6">
            <label>Manzana</label>
            <select
              formControlName="manzana"
              class="form-control custom-select"
              (change)="getVillas($event.target)"
            >
              >
              <option *ngFor="let ur of manzanas">
                {{ ur.manzana }}
              </option>
            </select>
          </div>
          <br />

          <div class="col-sm">
            <label>Villa</label>
            <select formControlName="villa" class="form-control custom-select">
              <option *ngFor="let ur of filtro" value="{{ ur.villa }}">
                {{ ur.villa }}
              </option>
            </select>
          </div>
          <br />
          ------------------------------------------------------------------------<br /> </ng-container
      ></ng-container>
    </form>
  </div>
</div>

I don't know what I could do or what would you recommend me to solve my problem, thank you very much

code in stackblitz Stackblitz


Solution

  • You have to create the separate value for filtro you can get help from the following code

    HTML

    <hello name="{{ name }}"></hello>
    <p>Start editing to see some magic happen :)</p>
    <div class="container">
     <div class="row">
    <div class="col-col-6">
      <label class="transparente"></label>
      <button (click)="addGroup()" type="button" class="btn btn-success">
        Agregar Campos filtro
      </button>
    </div>
    <br />
    <form [formGroup]="alicuotaForm">
      <ng-container
        formArrayName="times"
        *ngFor="
          let time of alicuotaForm.controls.times?.value;
          let i = index;
          trackBy: trackByFn
        "
      >
        <ng-container [formGroupName]="i" style="margin-bottom: 10px;">
          Iteracion {{ i + 1 }}
          <div class="col-col-6">
            <label>Manzana</label>
            <select
              formControlName="manzana"
              class="form-control custom-select"
              (change)="getVillas($event.target, i)"
            >
              >
              <option *ngFor="let ur of manzanas">
                {{ ur.manzana }}
              </option>
            </select>
          </div>
          <br />
    
          <div class="col-sm">
            <label>Villa</label>
            <select formControlName="villa" class="form-control custom-select">
              <option *ngFor="let ur of filtro[i]" value="{{ ur.villa }}">
                {{ ur.villa }}
              </option>
            </select>
          </div>
          <br />
          ------------------------------------------------------------------------<br /> </ng-container
      ></ng-container>
    </form>
    

    Typescript

      import { Component, VERSION } from '@angular/core';
      import {
        FormControl,
        FormGroup,
        FormBuilder,
        FormArray,
        Validators,
        FormGroupDirective,
     } from '@angular/forms';
    
      @Component({
        selector: 'my-app',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css'],
      })
     export class AppComponent {
    name = 'Angular ' + VERSION.major;
    villas = [
      { manzana: '1', villa: '10' },
      { manzana: '1', villa: '20' },
      { manzana: '1', villa: '30' },
      { manzana: '2', villa: '40' },
      { manzana: '2', villa: '50' },
      { manzana: '2', villa: '60' },
      { manzana: '3', villa: '70' },
      { manzana: '3', villa: '80' },
      { manzana: '3', villa: '90' },
    ];
    filtro: any[]=[];
    manzanas = [{ manzana: '1' }, { manzana: '2' }, { manzana: '3' }];
    alicuotaForm: FormGroup;
    value = this.fb.group({
      manzana: ['', Validators.required],
      villa: ['', Validators.required],
    });
    nregistros: number;
    
    constructor(private fb: FormBuilder) {}
    
    ngOnInit() {
      this.alicuotaForm = this.fb.group({
        times: this.fb.array([]),
      });
    }
    getVillas(value,index) {
      console.log('valor: ', value.value);
      this.filtro[index] = this.filtro[index].filter(x => x.manzana === value.value);
    }
    addGroup() {
      const val = this.fb.group({
        manzana: ['', Validators.required],
        villa: ['', Validators.required],
      });
      
      const alicuotaForm = this.alicuotaForm.get('times') as FormArray;
      alicuotaForm.push(val);
      this.nregistros = alicuotaForm.length;
      this.filtro.push(null);
      this.filtro[this.nregistros-1]=[...this.villas];
    }
    
    removeGroup(index) {
      const alicuotaForm = this.alicuotaForm.get('times') as FormArray;
      alicuotaForm.removeAt(index);
    }
    
    trackByFn(index: any, item: any) {
      return index;
    }
      }