角复杂组件通信

时间:2018-07-22 09:25:44

标签: angular

我是Angular的新手,我的任务似乎找不到最佳的方法。我有一个具有3个子组件的父组件,看起来像下面的图片。

当用户单击父控制器中的“保存”按钮时,如果表单有效,则来自“子1”和“子3”的所有表单输入以及来自“子2”的项目列表必须为保存到数据库中。只需调用一次Web api,就可以发送一个对象(该对象将包含一些字符串和一系列项目)。

我已经阅读了父组件和子组件之间进行通信的多种方法,但是我不确定在这种情况下最好的方法是什么。 如果我使用ViewChild,则父级将了解其他组件,因此它们将紧密结合在一起。 如果我使用Input / Output,那么我必须找到一种方法来点击所有值,但是仅在表单有效的情况下(我还没有找到方法) 如果我使用服务,我不知道它对表单有效性和返回表单值有帮助吗?

对于这些情况,当父级与多个子组件和复杂对象通信时,是否有最佳方法?任何有关此主题的信息或帮助将不胜感激。

enter image description here

4 个答案:

答案 0 :(得分:0)

表单具有value and status changed events,更确切地说是可观察的。您可以为将代表此功能的子组件创建组件输出。一项更改值,另一项更改状态。无论何时触发它们,您都会在输出上发出新事件。

这样,在父组件中,您将始终始终具有所有表单的状态和值,并且可以在用户单击“保存”按钮时使用。例如,如果并非所有表格都有效,您也可以禁用该按钮。

答案 1 :(得分:0)

您的任务并不简单。我想重点是它是大形式。可能会出现验证问题。从Reactive Form开始,按FormGroup制作嵌套表单,如果需要使用绑定机制将其拆分为子组件。相关文章Angular2: Building nested, reactive forms

答案 2 :(得分:0)

app.component.ts

import { Component, ViewChild } from "@angular/core";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  title = "app";

  @ViewChild("child1Component") child1: any;
  @ViewChild("child2Component") child2: any;
  @ViewChild("child3Component") child3: any;

  save() {
    console.log(this.child1.form.value);
    console.log(this.child2.form.value);
    console.log(this.child3.form.value);
  }
}

app.component.html

 Parrent

    <button type="submit" (click)="save()" [disabled]="!child1.form.valid || !child2.form.valid || !child3.form.valid"> Save </button>

    <app-child1 #child1Component></app-child1>
    <app-child2 #child2Component></app-child2>
    <app-child3 #child3Component></app-child3>

child1.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: 'app-child1',
  templateUrl: './child1.component.html',
  styleUrls: ['./child1.component.css']
})
export class Child1Component implements OnInit {


  @ViewChild("child1Form") form: any;

  constructor() { }

  ngOnInit() {
  }

}

child1.component.html

<div class="container">
  <h1>Child 1</h1>
  <form #child1Form="ngForm">
    <div class="form-group">
      <input type="text" class="form-control" name="input1" [(ngModel)]="input1" placeholder="Required" required>
    </div>

    <div class="form-group">
      <input type="text" class="form-control" name="input2" [(ngModel)]="input2">
    </div>


    <div class="form-group">
      <input type="text" class="form-control" name="input3" [(ngModel)]="input3">
    </div>


    <div class="form-group">
      <input type="text" class="form-control" name="input4" [(ngModel)]="input4">
    </div>

  </form>
</div>

添加两个与child1.component.ts和child1.component.html相同的子组件

此外,我还添加了必填字段验证功能,并基于该保存按钮已禁用和启用。

答案 3 :(得分:0)

这不是最简单的任务。但是我强烈建议您使用反应形式。然后,您可以使用Angulars FormGroup在父组件中创建一个FormBuilder

form: FormGroup;

constructor(private fb: FormBuilder) {
  this.form = this.fb.group({
    subform1: this.fb.group({
      input1: null,
      input2: 'thisisastring'
    }),
    subform2: this.fb.group({
      input1: null,
      input2: null
    })
  })
}

get subform1(): FormGroup {
  return this.form.get('subform1') as FormGroup;
}

现在,您可以在模板中将子表单组作为输入传递。

<form [formGroup]="form" (ngSubmit)="functionToSave(form.value)">
   <app-subform1 [form]="subform1"></app-subform1>
</form>

在您的组件中,您现在可以创建上面的表单

@Input() form: FormGroup;

像这样在您的模板中使用它

<div [formGroup]="form">
  <input formControlName="input1">
</div>

,不使用form标签。然后,在父组件中创建functionToSave函数来处理所有数据。为了进行验证,只需从@ angular / forms导入Validators并像这样使用FormBuilder

this.form = this.fb.group({
    subform1: this.fb.group({
      input1: [null, Validators.required]
    })
})