【问题标题】:Pass the data to next step in component based mat-stepper将数据传递到基于组件的 mat-stepper 中的下一步
【发布时间】:2020-06-15 21:27:22
【问题描述】:

我正在使用基于组件的 mat stepper 组件来显示线性过程。每个步骤都有自己的组件,如下所示

<mat-card>
    <mat-horizontal-stepper [linear]="isLinear" labelPosition="bottom" #stepper>
    
    <!-- Step-1 -->
    <mat-step [stepControl]="firstFormGroup">
       <ng-template matStepLabel>Select Items</ng-template>
       <select-item-component>
       <select-item-component>
       <div class="mt-5">
          <button mat-flat-button color="primary" matStepperNext>Next</button>
       </div>
    </mat-step>
    
    <!-- Step-2 -->
    <mat-step [stepControl]="firstFormGroup">
       <ng-template matStepLabel>Add Quantity</ng-template>
       <add-qty-component>
       <add-qty-component>
       <div class="mt-5">
          <button mat-flat-button color="primary" matStepperNext>Next</button>
       </div>
    </mat-step>
    
    <!-- Step-3 -->
    <mat-step [stepControl]="firstFormGroup">
       <ng-template matStepLabel>Conform</ng-template>
       <conform-step-component>
       <conform-step-component>
       <div class="mt-5">
          <button mat-flat-button color="primary" matStepperNext>Done</button>
       </div>
    </mat-step>
    </mat-horizontal-stepper>
 </mat-card>

Step-1 显示可多选的项目列表,并将选定的项目列表传递到下一个 step-2,并在 step-2 中添加每个项目的数量。

如何在 Next click 从 step-1 到 step-2 传递选定的项目并显示传递的项目以在 step-2 中输入数量?

我创建了一个通用服务层来设置和获取选定的项目。 ngOnInit 的步骤 2 的组件试图从公共服务中获取所选列表,但问题是组件 2 在下次单击之前已启动。

第1步点击next后可以初始化或重新初始化第二个组件吗?

从步骤 1 移动后如何显示步骤 2 中的选定项目列表?

上述场景的最佳方法是什么?

只要一个可以回答我问题的参考资料的链接就足够了。

谢谢。

【问题讨论】:

  • 您还在寻找解决方案还是找到了??

标签: javascript angular components mat-stepper


【解决方案1】:

要使组件输出值,请使用@Output

要使用组件外部的数据,请使用@Input

由于我不知道您的商品类型,我将在此示例中使用 ItemType

选择项目组件

在 select-item-component 中,声明一个属性:

@Output() onDataChange: EventEmitter<ItemType> = new EventEmitter();

以及选择更改时,刚执行

this.onDataChange.emit(formValue);

添加数量组件

@Input() item: ItemType;

如果您想在值更改时触发某些操作,请使用set。例如:

@Input() set item(value: ItemType) {
  this.loadOptions(value);
}

您可以在 select-item-component 中使用 select1select2 变量执行相同的操作。

父母

使用输出和输入值。

...
<select-item-component (onDataChange)="select1 = $event"></select-item-component>
<select-item-component (onDataChange)="select2 = $event"></select-item-component>

...

<add-qty-component [item]="select1"></add-qty-component>
<add-qty-component [item]="select2"></add-qty-component>
...

【讨论】:

    【解决方案2】:

    您可以结合使用@Output 和@Input 装饰器。

    @Output 装饰器可用于子组件(stepper 1)将数据传输到其父组件。

    @input 装饰器可用于将数据从父组件发送到子组件(步骤 2)。

    您可以阅读更多关于它的信息here

    【讨论】:

      【解决方案3】:

      您可以将ControlContainer 用于相同目的,它允许您访问子组件和父组件中的表单控件

      <button mat-raised-button (click)="isLinear = !isLinear" id="toggle-linear">
        {{!isLinear ? 'Enable linear mode' : 'Disable linear mode'}}
      </button>
      <mat-horizontal-stepper [linear]="isLinear" #stepper>
        <mat-step [stepControl]="firstFormGroup">
          <form [formGroup]="firstFormGroup">
            <ng-template matStepLabel>Fill out your name</ng-template>
           <step1></step1>
            <div>
              <button mat-button matStepperNext>Next</button>
            </div>
          </form>
        </mat-step>
        <mat-step [stepControl]="secondFormGroup">
          <form [formGroup]="secondFormGroup">
            <ng-template matStepLabel>Fill out your address</ng-template>
            <step2></step2>
            <div>
              <button mat-button matStepperPrevious>Back</button>
              <button mat-button matStepperNext>Next</button>
            </div>
          </form>
        </mat-step>
      </mat-horizontal-stepper>
      

      你的Step1 组件应该看起来像

      import {Component, OnInit} from '@angular/core';
      import {ControlContainer, FormGroup, Validators} from '@angular/forms';
      
      
      @Component({
        selector: 'step1',
        template:`
        <form [formGroup]="form"> 
         <mat-form-field>
              <mat-label>Name</mat-label>
              <input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
            </mat-form-field>
        </form>
        `
      })
      export class Step1 implements OnInit {
        isLinear = false;
        form: FormGroup;
      
        constructor(private controlContainer:ControlContainer) {}
      
        ngOnInit() {
         this.form=<FormGroup>this.controlContainer.control;
         this.form.valueChanges.subscribe(data=>console.log(data));
        }
      }
      

      你的Step2 组件看起来像

      import {Component, OnInit} from '@angular/core';
      import {ControlContainer, FormGroup, Validators} from '@angular/forms';
      
      /**
       * @title Stepper overview
       */
      @Component({
        selector: 'step2',
        template:`
        <form [formGroup]="form"> 
          <mat-form-field>
              <mat-label>Address</mat-label>
              <input matInput formControlName="secondCtrl" placeholder="Ex. 1 Main St, New York, NY"
                     required>
            </mat-form-field>
        </form>
        `
      })
      export class Step2 implements OnInit {
        form: FormGroup;
      
        constructor(private controlContainer:ControlContainer) {}
      
        ngOnInit() {
         this.form=<FormGroup>this.controlContainer.control;
         this.form.valueChanges.subscribe(data=>console.log(data));
        }
      }
      

      stackblitz

      【讨论】:

        【解决方案4】:

        另一种选择是使用共享服务。我会在服务上使用主题,并在更改数据的组件中调用 next,在下一次调用时传递新数据。

        public $itemsAdded: Subject<Item> = new Subject<Item>();
        

        然后在下一个组件中,订阅您的主题并将您的本地变量设置为该数据。

        this.sharedService.$itemsAdded.subscribe(items => {
          this.items = items.map(x => mapItem());
        });
        

        【讨论】:

        • 为了防止不必要的行为,您应该使用 replaySubject 或 behaviorSubject。因为否则很容易,在 $itemsAdded 上调用 next 并在之后订阅主题。有了behaviourSubject,你就不应该有这个问题。如果您没有 *Subject 的初始值,您可以像这样使用 replaySubject:public $itemsAdded: ReplaySubject&lt;Item&gt; = new ReplaySubject(1)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-20
        • 1970-01-01
        • 1970-01-01
        • 2019-11-02
        • 2020-11-08
        • 2018-03-23
        • 2019-11-15
        相关资源
        最近更新 更多