在Angular 6中将多个组件中的数据收集到一个的最佳方法

时间:2018-12-04 08:13:30

标签: angular angular-material

我对Angular来说还比较陌生,我知道我的问题可能很原始,但是请为我提供最佳解决方案。

我有一个步进器(来自角材料);每个步骤的内容位于不同的组件中;在所有步骤中,我们都使用多个输入字段从客户那里收集数据。

代码如下。

步进:

<mat-horizontal-stepper #stepper>
  <mat-step [stepControl]="stepOne">
    <ng-template matStepLabel><span class="someClass">Customer Information</span></ng-template>

    <step-one></-step-one>

  </mat-step>
  <mat-step [stepControl]="stepTwo">
    <ng-template matStepLabel><span class="someClass">Payment Information</span></ng-template>

    <step-two></step-two>

  </mat-step>
    ...
  <mat-step>
    <ng-template matStepLabel><span class="someClass">Confirmation</span></ng-template>

    <confirmation></confirmation>

  </mat-step>
</mat-horizontal-stepper>

内容(很多类似的字段):

  <mat-form-field class="dcp-input-field">
    <input matInput placeholder="First Name" formControlName="name" [errorStateMatcher]="matcher">
      ...
  </mat-form-field>

我想要的是收集最后一个“确认”控制器中的所有数据,以将其显示给客户。我知道组件之间存在多种通信方式,但是在这种情况下哪一种是最好的? 我尝试使用服务,但是出了点问题。

请给我发送指向可以回答我的问题的任何参考的链接,就足够了。

感谢您的咨询。

4 个答案:

答案 0 :(得分:2)

服务不是您所需要的正确解决方案。

您应该将数据对象放在父组件中,并将其作为input传递给所有子组件(步骤)。

修改

示例代码:

父母

在父组件中定义数据对象:

data = {};

将数据对象传递给父模板中的第一步子组件:

<mat-horizontal-stepper #stepper>
  <mat-step [stepControl]="stepOne">
    <ng-template matStepLabel><span class="someClass">Customer Information</span></ng-template>
    <step-one [data]="data"></-step-one>
  </mat-step>
  ...

孩子

定义@Input数据对象以从父级接收:

@Input() data: {};


摘要:通过这种方式,所有子项都可以使用父级的数据对象,并且一旦在父级组件中提交,数据就在那里。

答案 1 :(得分:1)

您可以编写一个为您保存变量的服务,在每一步中,您将服务中的变量设置为需要保存的数据。然后,当您完成步进时,服务中的所有数据将准备就绪并等待。

这是Angular文档。 Docs

使用该服务,设置一个函数,该函数按所需顺序返回所需的所有数据,并在最后一步进行预订,如下所示。  Subscriptions

然后,在步进程序结束时需要时,应该拥有所有数据。

请记住,当您使用完数据清除服务中保留的所有变量时,避免步进器返回错误数据的任何问题。

答案 2 :(得分:1)

如果您想使用viewChild进行操作,可以采取以下方式:

第一个子组件

import { Component } from '@angular/core';

@Component({
  selector: 'cmp-1',
  template: ''
})
export class Cmp1Component  {
  public data: any[] = [
    {
      name: "component 1",
      action: "something",
      status: "alive"
    }
  ]
}

第二个子组件

import { Component } from '@angular/core';

@Component({
  selector: 'cmp-2',
  template: ''
})
export class Cmp2Component  {
  public data: any[] = [
    {
      name: "component 2",
      action: "something else",
      status: "not alive"
    }
  ]
}

主要组件使用ViewChildren获取数据

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('cmp1') component1: Cmp1Component;
  @ViewChild('cmp2') component2: Cmp2Component;
}

相关的html和CSS

<cmp-1 #cmp1></cmp-1>
<cmp-2 #cmp2></cmp-2>

<h1>Here's the data from the components</h1>

<hr>

<h3>Component 1</h3>

<div class="box">
  <div class="item" *ngFor="let data of component1.data">
    <div>{{data.name}}</div>
    <div>{{data.action}}</div>
    <div>{{data.status}}</div>
  </div>
</div>

<hr>

<h3>Component 2</h3>

<div class="box">
  <div class="item" *ngFor="let data of component2.data">
    <div>{{data.name}}</div>
    <div>{{data.action}}</div>
    <div>{{data.status}}</div>
  </div>
</div>

.box{
  display: flex;
  flex-direction: column;
}

注意,在此示例中,我没有检查两个组件是否都存在,因为我确定地知道这两个组件,因为它们都是静态的。在做一些逻辑之前,请务必检查它们是否已被证实。

有效的堆叠闪电战:https://stackblitz.com/edit/angular-n1tunk

答案 3 :(得分:0)

我知道并会推荐的两种方法。

  1. 您的步进器位于父组件中,每个步骤都有一个带有输出绑定的子组件。您的父母在这些变量component-interaction

  2. 上获得了更改
  3. 每个子组件向其发送数据的服务,并在其中构建数组/对象。然后将其从服务发送到父级。

我会推荐第一种具有输出绑定的解决方案