角度 - 角度材料2步进控制

时间:2017-10-25 18:05:07

标签: angular angular-material2 angular4-forms

我使用Angular Material 2 Stepper设置了一个线性步进器。

我在不同的组件中有表单(component-a,component-b,component-c)。在我的主容器组件(容器组件)中,我希望线性步进器在其表单有效时“逐步”遍历每个组件。

是否有某种功能可以与步进器中的stepControl对话以使其正常工作?

我附上了步进器的文档和应用程序的StackBlitz版本。另外,我也有工作的回购链接。

物料步进器组件:https://material.angular.io/components/stepper/overview

StackBlitz:https://stackblitz.com/edit/angular-material2-issue-mjmu9u?file=app/app.component.ts

Github:https://github.com/sam11385

2 个答案:

答案 0 :(得分:8)

我们遇到了完全相同的问题,经过几天的试验和错误后找到了一个有效的解决方案。基本上,由于步骤分为几个组件,每个组件都定义一个表单,并且它们对应的stepControl必须在父组件中,因此必须将子组件中的FormGroup发送到定义步进器的父组件。创建FormGroup之后,发出一个事件并让父级监听该事件,并通过该事件传递FormGroup。您可以为所有子项应用此项,为每个子项创建一个单独的事件,并为每个子项创建一个单独的侦听器。

在子组件中:

  1. 宣布活动

    @Output() notify: EventEmitter<FormGroup> = new EventEmitter<FormGroup>();                                                                                                         
    
  2. 将formGroup发送到父组件

    this.notify.emit(this.myFormGroup);                                                                                                                                                
    
  3. 在包含mat-stepper的stepControl(s)的父组件中:

    1. 在组件(.ts)中,添加一个将接收和设置表单组的函数:

      myFormGroup: FormGroup;
      onNotify(formGroup: FormGroup): void {
        this.myFormGroup = formGroup;
      }
      
    2. 在html中,添加通知监听器:

      <mat-step [completed]="false" [stepControl]="myFormGroup">
        <ng-template matStepLabel>Step 1</ng-template>
        <app-child (notify)='onNotify($event)'></app-child>
      </mat-step>                                                                                                                                            
      
    3. 嵌套组件说明:https://www.themarketingtechnologist.co/building-nested-components-in-angular-2/

答案 1 :(得分:2)

上面的答案很明显,但是在我的特定用例中我遇到了一些更深层次的问题,所以我用共享服务解决了这个问题:

<强>形状management.service.ts

import { Injectable } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class FormManagementService {

    private formSource: Subject<FormGroup> = new Subject();
    locationForm: Observable<FormGroup> = this.formSource.asObservable();

    formReady(form: FormGroup): void {
        this.formSource.next(form);
    }
}

<强> parent.component.ts

import { Component } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormManagementService } from './form-management.service';

@Component({
    ....
    providers: [ FormManagementService ]
})
export class ParentComponent {

    form: FormGroup;

    constructor(private formManagementService: FormManagementService) {
        this.formManagementService.locationForm.subscribe(form => this.form = form);
    }

}

注意,这里我们订阅了共享服务的更改,它将在需要时将表单传递给组件。当父组件收到表单时,它会填充FormGroup。

另请注意,我们在此处提供共享服务作为组件装饰器的一部分。您也可以在功能模块中提供它,如果这是您的代码的结构方式。

<强> child.component.ts

import { Component } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { FormManagementService } from './form-management.service';

@Component({ ... })
export class ChildComponent {

    form: FormGroup;

    constructor(private formManagementService: FormManagementService,
                private formBuilder: FormBuilder) {
        this.form = this.formBuilder.group({});
        this.formManagementService.formReady(this.form);
    }

}

在子组件中,我们初始化表单,然后将其推送到共享服务,共享服务将在父组件中填充它。

注意,我发现如果我在构造函数以外的任何地方执行此操作,那么当我在ExpressionChangedAfterItHasBeenCheckedError中执行此操作时,我遇到了ngAfterContentInit甚至。也许其他人会在我的解决方案上有进一步的进步来解决这个问题。

无论如何,希望这对那里的某些人有所帮助,因为这个问题困扰了我几个星期。