【问题标题】:select option independent in formArray Angular在 formArray Angular 中选择独立的选项
【发布时间】:2022-01-13 01:25:34
【问题描述】:

晚上好,我有一个问题,我使用的是反应式表单,使用 FormArray,我有一个按钮可以根据需要多次添加 2 个选项,问题是这些选项是 matselects,我在其中一个选择中使用一个事件(更改),问题是第一次添加选项 onchange 工作正常,但是当添加选项超过 2 倍时,之前在 matselects 中选择的值会发生变化,因为创建的 select 的 onchange 是 re -执行。 我想知道是否有办法在 formArray 的每次迭代中独立使用该事件

组件.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>

我不知道我能做什么或者你会建议我解决什么 我的问题,非常感谢

stackblitz 中的代码 Stackblitz

【问题讨论】:

    标签: javascript angular typescript angular-reactive-forms formarray


    【解决方案1】:

    您必须为 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;
    }
      }
    

    【讨论】:

      【解决方案2】:

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

      1. (我推荐)创建自定义Pure 管道以返回过滤后的别墅列表。纯管道只会在值发生变化时执行,而不是在每个绘制周期中执行。
      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 执行 *ngFor 时,您将引用此表单控件的值
      2. 在您的组件中创建一个函数,根据数组项的 manzana 过滤别墅(不推荐,因为这会重新计算每个绘制周期)。

      【讨论】:

        猜你喜欢
        • 2023-03-15
        • 2019-08-18
        • 2020-07-07
        • 2023-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-30
        • 1970-01-01
        相关资源
        最近更新 更多