Angular 2 react形式的嵌套数组?

IT技术 javascript angular typescript
2021-02-21 18:36:56

我已经使用以下教程在 Angular 2 中创建react式表单,并且效果很好。

https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

但是,我现在正在尝试在数组中添加一个数组。使用上面的教程,我创建了一个“组织”表单,其中可以包含一组“联系人”组。但是我无法成功调整设置以允许每个“联系人”组包含一组“电子邮件”组。

我一直无法找到涵盖此内容的教程或示例,如果您有任何指点,我将不胜感激。

1个回答

使用上面的教程,我创建了一个“组织”表单,其中可以包含一组“联系人”组。但是我无法成功调整设置以允许每个“联系人”组包含一组“电子邮件”组。

上面的教程为您提供了所需的一切。

我想你想要这样的结构。

在此处输入图片说明

首先,您需要一些AppComponent声明 root 的组件(在我的情况下)FormGroup我在trustForm下面称它

app.component.ts

export class AppComponent {
  trustForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.trustForm = this.fb.group({
      name: '',
      contracts: this.fb.array([])
    });

    this.addContract();
  }

  initContract() {
    return this.fb.group({
      name: '',
      emails: this.fb.array([])
    });
  }

  addContract() {
    const contractArray = <FormArray>this.trustForm.controls['contracts'];
    const newContract = this.initContract();

    contractArray.push(newContract);
  }

  removeContract(idx: number) {
    const contractsArray = <FormArray>this.trustForm.controls['contracts'];
    contractsArray.removeAt(idx);
  }
}

在这个组件中,您还有一些方法可以帮助您操作第一级FormArray-contracts

应用程序组件.html

<div class="container">
    <form [formGroup]="trustForm">
        <h3>Add trust</h3>

        <div class="form-group">
            <label>Name</label>
            <input type="text" class="form-control" formControlName="name">
        </div>

        <!--contracts-->
        <div formArrayName="contracts">
            <div *ngFor="let contract of trustForm.controls.contracts.controls; let i=index" class="panel panel-default">
                <div class="panel-heading">
                    <span>Contract {{i + 1}}</span>
                    <span class="glyphicon glyphicon-remove pull-right" *ngIf="trustForm.controls.contracts.controls.length > 1" (click)="removeContract(i)"></span>
                </div>
                <div class="panel-body" [formGroupName]="i">
                    <contract [group]="trustForm.controls.contracts.controls[i]"></contract>
                </div>
            </div>
        </div>
        <div class="margin-20">
            <button (click)="addContract()" class="btn btn-primary">
                Add another contract +
            </button>
        </div>

    </form>

    <h5>Details</h5>
    <pre>{{ trustForm.value | json }}</pre>
</div>

除了FormArray名称不同之外,与教程中的root html没有区别

然后你需要构建类似于 AppComponent

合约.component.ts

export class ContractComponent {
    @Input('group') contractGroup: FormGroup;

    constructor(private fb: FormBuilder) { }

    addEmail() {
        const emailArray = <FormArray>this.contractGroup.controls['emails'];
        const newEmail = this.initEmail();

        emailArray.push(newEmail);
    }

    removeEmail(idx: number) {
        const emailArray = <FormArray>this.contractGroup.controls['emails'];
        emailArray.removeAt(idx);
    }

    initEmail() {
        return this.fb.group({
            text: ''
        });
    }
}

合同.component.html

<div [formGroup]="contractGroup">
    <div class="form-group">
        <label>Name</label>
        <input type="text" class="form-control" formControlName="name">
    </div>

    <!--emails-->
    <div formArrayName="emails">
        <div *ngFor="let email of contractGroup.controls.emails.controls; let i=index" class="panel panel-default">
            <div class="panel-heading">
                <span>Email {{i + 1}}</span>
                <span class="glyphicon glyphicon-remove pull-right" *ngIf="contractGroup.controls.emails.controls.length > 1" (click)="removeEmail(i)"></span>
            </div>
            <div class="panel-body" [formGroupName]="i">
                <email [group]="contractGroup.controls.emails.controls[i]"></email>
            </div>
        </div>
    </div>
    <div class="margin-20">
        <button (click)="addEmail()" class="btn btn-primary">
            Add another email +
        </button>
    </div>

</div>

正如你所看到的,我们只是替换contractsemails FormArray,我们也传递FormGroup给电子邮件组件

最后,您只需要填写EmailComponent所需的字段。

email.component.ts

export class EmailComponent {
    @Input('group') emailGroup: FormGroup;
}

电子邮件.组件.html

<div [formGroup]="emailGroup">
    <div class="form-group">
        <label>Text</label>
        <input type="text" class="form-control" formControlName="text">
    </div>
</div>

您可以在Plunker 示例中找到完整版本

如果你认为,因为父组件拥有像子组件的描述这个解决方案似乎并不正确initContract,并initEmails可以看看更复杂

Plunker 示例

每个组件负责其功能。

如果您正在寻找模板驱动表单的解决方案,请阅读这篇文章:

很抱歉我花了很长时间才承认这一点,但这正是我所需要的。一旦你看到它完成就很有意义:) 谢谢!
2021-04-25 18:36:56
在这篇文章中,您构建新表单,像这样我想为现有数组构建表单
2021-05-12 18:36:56
当您在stackoverflow.com/questions/43205237/... 中回答时,我对我的概念有类似的要求,但是您映射了表单组。实际上,我的值首先在 '.ts' 文件中构建,然后通过 '.ts' 文件我正在使用 ng-for 在表单组中重复值。我的 html 表单应该如问题中所述。请帮助我摆脱这种情况。
2021-05-14 18:36:56