首页 文章

嵌套角度反应形式和组件重用

提问于
浏览
0

TL;DR :将嵌套组件与嵌套reactive forms组合似乎有问题 . 每个嵌套组件都必须从[formGroupName][formArrayName][formControlName]指令的组合构建整个表单层次结构 .

Detail :给定键值对建模为:

{
    "key": string,
    "value": string
}

single 键值对和 list 键值对可以建模为:

{
  "one": {
    "key": "Key A",
    "value": "Value A"
  },
  "many": [
    {
      "key": "Key A",
      "value": "Value A"
    },
    {
      "key": "Key B",
      "value": "Value B"
    },
    {
      "key": "Key C",
      "value": "Value C"
    }
  ]
}

它看起来像Angular Reactive Forms和嵌套的 @Component 的组合应该使这个微不足道 .

我创建了以下组件层次结构和项目结构:

│   app.component.html
│   app.component.ts
│   app.module.ts
│
├───key-value
│       key-value.component.html
│       key-value.component.ts
│
└───key-value-list
        key-value-list.component.html
        key-value-list.component.ts

应用程序组件 app.component.ts 定义了一个模型,并使用FormBuilder构建了相应的FormGroup

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html'
})
export class AppComponent {
  public form: FormGroup;
  public model = {
    one: {
      key: 'Key A',
      value: 'Value A'
    },
    many: [
      {
        key: 'Key A',
        value: 'Value A'
      },
      {
        key: 'Key B',
        value: 'Value B'
      },
      {
        key: 'Key C',
        value: 'Value C'
      }
    ]
  };

  constructor(private readonly fb: FormBuilder) { }

  public ngOnInit(): void {
    const items: FormGroup[] = this.model.many.map(pair => {
      return this.fb.group(pair);
    });

    this.form = this.fb.group({
      one: this.fb.group(this.model.one),
      many: this.fb.array(items)
    });
  }
}

一开始介绍的模型应该很容易识别 . form 包含两个控件,FormGroupFormArray分别用于 key-valuekey-value-list . FormArrayFormGroup的列表 .

app.component.html 提供 key-value 对应属于的控制组的顶级 formname

<key-value [parentForm]="form" name="one"></key-value>
<pre>{{ form.value | json }}</pre>

传输表单值以进行调试和格式化( <pre> ) . key-value.component.ts 接受两个 Input() 值并且非常非常少(所有工作都在视图中完成):

@Component({
  selector: 'key-value',
  templateUrl: './key-value.component.html'
})
export class KeyValueComponent {
  @Input() public parentForm: FormGroup;
  @Input() public name: string;
}

工作在 key-value.component.html 中完成,使用两个 Input() 值构建控件层次结构:

<div [formGroup]="parentForm">
    <div [formGroupName]="name">
        <mat-form-field>
            <input matInput formControlName="key" placeholder="Key">
        </mat-form-field>
        <mat-form-field>
            <input matInput formControlName="value" placeholder="Value">
        </mat-form-field>
    </div>
</div>

列表视图类似:

<div [formGroup]="parentForm">
    <div [formArrayName]="name">
        <div *ngFor="let c of parentForm.get(name).controls; let i=index;" [formGroupName]="i">
            <mat-form-field>
                <input matInput formControlName="key" placeholder="Key">
            </mat-form-field>
            <mat-form-field>
                <input matInput formControlName="value" placeholder="Value">
            </mat-form-field>
        </div>
    </div>
</div>

这有效 . 但我想重新使用 key-value-list 组件中的 key-value 组件,但我正在撞墙 . 假设我的应用程序视图变为:

<div [formGroup]="parentForm">
    <div [formArrayName]="name">
        <div *ngFor="let c of parentForm.get(name).controls; let i=index;" [formGroupName]="i">
            <key-value [parentForm]="??????" name="??????"></key-value>
        </div>
    </div>
</div>

这似乎是一个合理的开始,但我不知道循环内部应该是什么 .

1 回答

  • 0

    实际上,您不需要将FormGroup实例和FormGroupName都传递给子组件,任何一个都可以 . 数组比单一控件有点棘手,但这样的东西应该有效:

    <div [formGroup]="parentForm">
        <div [formArrayName]="name">
            <div *ngFor="let c of parentForm.get(name).controls; let i=index;">
                <key-value [parentForm]="c"></key-value>
                <!--<key-value [name]="i"></key-value> this should also work-->
            </div>
        </div>
    </div>
    

相关问题