select 选项独立于 formArray Angular

select option independent in formArray Angular

晚上好,我有一个问题我正在使用反应式表单,使用 FormArray,我有一个按钮可以根据需要多次添加 2 个选项,问题是选项是 matselects在其中一个 select 中,我使用了一个事件(更改),问题是第一次添加选项时 onchange 工作正常,但是当添加的选项是以前的值的 2 倍以上时 selected in the matselects change 因为创建的select的onchange被重新执行了。 我想知道是否有办法在 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

stackblitz 中的代码 Stackblitz

您必须为 filtro 创建单独的值您可以从以下代码中获得帮助

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>

打字稿

  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;
}
  }

据我所知,您的主要问题是您有一个变量 filtro,您正试图将其用于 FormArray 中的所有元素。您可以:

  1. (我的推荐)创建一个自定义 Pure 管道到 return 过滤别墅列表。纯管道只会在值更改时执行,而不是每个绘制周期。
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'arrayFilter' })
export class ArrayFilterPipe implements PipeTransform {
  transform(arr: any[], property: string, value: any): any {
    return arr.filter((x) => x[property] === value);
  }
}

然后您可以像这样在您的模板中使用它(不要忘记在您的模块中声明它):

<select formControlName="villa" class="form-control custom-select">
  <option
    *ngFor="let ur of (villas | arrayFilter: 'manzana': time.manzana)"
    value="{{ ur.villa }}"
  >
    {{ ur.villa }}
  </option>
</select>

打字稿:

addGroup() {
    // either provide a '' option to this.manzanas, or set manzana: '1' to avoid expression after checked errors
    const val = this.fb.group({
      manzana: ['1', Validators.required],
      villa: ['', Validators.required],
    });
    const alicuotaForm = this.alicuotaForm.get('times') as FormArray;
    alicuotaForm.push(val);
    this.nregistros = alicuotaForm.length;
  }

有关详细信息,请参阅 Pipes

  1. 在名为 filtro 的组中创建另一个表单控件,然后在 getVillas 函数中设置它的值。然后,当您为表单控件 villa
  2. 执行 *ngFor 时,您将引用此表单控件的值
  3. 在您的组件中创建一个函数,根据数组项的 manzana 过滤别墅(不推荐,因为这会重新计算每个绘制周期)。