从 Angular 中的数组动态创建 formControl

Create formControl dynamically from Arrays in Angular

这是我的第一个问题,所以我希望我准备得足够充分,能够准确地解释问题。 I've also created a stackblitz example for my problem

我从后端收到以下字符串,它应该显示在 table 中。 ('1,2,3@12.5,22.5,27.5@,,''10,8,5,3,2@17.5,25,32,47,63@2,2,1,0,')。长度可以变化。它是 3 个参数(以 @ 分隔)和相应的迭代及其值(以 , 分隔)。

目前我使用 [value] 访问器和 change 方法来拆分字符串并重新组合它。我现在想为各自的值使用一个验证器,它只能与 formControlName 结合使用。 (我知道它也适用于 ngModel,但这只是一个摘录,我们已经在为其他属性使用表单模块)。

我编写了一个验证器,它在我的示例中的第一个输入字段中使用并按预期工作(稍后将出现几个正则表达式,但对于示例我只选择了一个简单的)。

我的问题是:是否可以拆分字符串并将其转换为 FormControls?然后如何访问它并在 HTML?

中显示它

我知道 FormArrays,但不太了解它,因为这是 FormArray 中的一个 FormArray(我猜?-一个用于参数,一个用于迭代值)

我的下一个方法是在我当前的 setBlockValue 方法中包含对输入的验证,该方法在元素上设置一个 .invalid class,然后在输入字段下方显示错误文本。但是那仍然无法帮助我在提交时将表单标记为无效。

我希望这已经够清楚了,希望我的 stackblitz example 能有所帮助。我非常感谢可以解决我的问题的任何资源(如其他问题或文章)。只是还没找到合适的。

我不确定我是否完全理解您想要验证的内容(例如哪些字段),但这里有一个构建动态表单控件的建议:

初始化新表单组:

formGroup = new FormGroup({});

当你有字段(此处为 'yourFields',一个数组)时,你需要添加验证(正如我所说,我不确定那些字段是哪些),你可以遍历所有字段:

this.yourFields.forEach( (field,idx) => {
    const CONTROL = formGroup.controls[idx];
    this.formGroup.addControl(idx, new FormControl(field));
    let controlValidators = []; // if you're going to have more validators per field
    // you might also need to check the field (value) and add some custom validator etc.
    // so each validator you can push to this 'controlValidators  array:
    controlValidators.push(Validators.required); // or any other validator you want to push
    CONTROL.setValidators(controlValidators);
});

不完全了解你的数据结构,但似乎你需要这样的东西 (我们使用 ReactiveForms) 技术人员:

import { Component } from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title="Stack Overflow"
  form: FormGroup;
  blockValue = '10,8,5,3,2@17.5,25,32,47,63@2,2,1,0,';
  params = ['param1', 'param2', 'param3'];

  constructor(
    private _fb: FormBuilder
  ) { 
    //can be simplify, depend on aims
    this.form = _fb.group({
      block: _fb.array([])
    });
  }

  get block(): FormArray {
    return this.form.get('block') as FormArray;
  }

  ngOnInit(): void {
    this._buidForm();
    this.block.valueChanges
    .subscribe(values => {
      console.log(values);
    })
  }

  private _buidForm(): void {
    const data = this.blockValue.split('@').map(col => col.split(','));

    for (let i = 0; i < data[0].length; i++) {
      const group = this._fb.group({});
      this.params.map((param, idx) => {
        const control = this._fb.control(data[idx][i], Validators.required); //or other validators
        group.addControl(param, control)
      });

      this.block.push(group);      
    }
  }

  onSubmit(): void {
    console.log(this.form.value);
  }
}

HTML:

<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <table formArrayName="block">
    <tr>
      <td *ngFor="let param of params">{{param}}</td>
    </tr>
    <tr *ngFor="let group of block.controls; let i = index;" [formGroupName]="i">
      <td *ngFor="let col of params">
        <input type="text" [formControlName]="col" [style.background]="block.controls[i].get(col)?.invalid ? 'pink':'white'">
      </td>
    </tr>
  </table>
  <button type="submit" [disabled]="form.invalid">CHECK</button>
</form>