javascript - 嵌套的 Angular 响应式表单和组件重用

标签 javascript angular angular-reactive-forms angular4-forms

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

详细信息:给定键值对建模为:

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

单个键值对和列表键值对可以建模为:

{
  "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 , 定义了一个模型和对应的 FormGroup使用 FormBuilder 构建:

@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提供顶级 form和控制组的名称 key-value对应该属于:

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

表单值被管道输出用于调试和格式化(<pre>)。 key-value.component.ts接受两个 Input()值并且做的非常非常少(所有工作都在 View 中完成):

@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>

ListView 类似:

<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 key-value-list 中的组件组件,但我碰壁了。假设我的应用程序 View 变为:

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

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

最佳答案

实际上,您不需要将 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>

关于javascript - 嵌套的 Angular 响应式表单和组件重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48601544/

相关文章:

Angular 表单控件基于单选按钮选择进行验证

javascript - iOS UIAutomation 找不到搜索栏

javascript - 在 Google Chrome 之外测试 Jquery 链接

javascript - 加速选择器和方法

javascript - 显示我使用 @ContentChildren 或 @ViewChild 获取的组件的内容

angular - 当数据源为 Observable<T> 时,如何在 Angular Material Data Table 中启用排序

angular - 加载数据后设置 react 形式(异步)-Angular 5

javascript - 使用 angular.element 通过 ng-click 添加元素

javascript - 什么是更好的方法以及如何实现将对象从一个嵌套组件发送到另一个

angular - 每个表格行的 react 形式