Angular - Angular Material 2 步骤控件

5
我使用Angular Material 2 Stepper设置了一个线性步进器。
我有不同组件(component-a,component-b,component-c)中的表单。在我的主容器组件(container-component)中,我希望有一个线性步进器,当其表单有效时,“步进”到每个组件。
是否有某种功能可以与步进器中的stepControl进行交互,使其正常工作?
我附上了步进器的文档和应用程序的StackBlitz版本。还有一个我正在使用的工作库的链接。
Material Stepper Component: 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个回答

11

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

在子组件中:

  1. 声明事件

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

  3. this.notify.emit(this.myFormGroup);                                                                                                                                                
    

    在包含mat-stepper步骤控件的父组件中:

    1. 在组件(.ts)中添加一个接收并设置formgroup的函数:

    myFormGroup: FormGroup;
    onNotify(formGroup: FormGroup): void {
      this.myFormGroup = formGroup;
    }
    
    在HTML中,添加通知监听器:
  4. <mat-step [completed]="false" [stepControl]="myFormGroup">
      <ng-template matStepLabel>Step 1</ng-template>
      <app-child (notify)='onNotify($event)'></app-child>
    </mat-step>                                                                                                                                            
    

嵌套组件解释:https://www.themarketingtechnologist.co/building-nested-components-in-angular-2/


1
非常好的答案!! - Niroshan K
精彩的回答!谢谢。 - Vippy
这是我的代码,但它对我不起作用,你能帮我看一下吗?https://stackoverflow.com/questions/57909318/mat-stepper-every-step-in-component - cucuru
我收到了这个错误信息:ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: '[object Object]'。 - vigamage

2
上面的答案非常准确,但在我的特定用例中,我遇到了一些更深层次的问题,因此我使用了一个共享服务来解决它:
form-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”中进行操作。也许其他人会对我的解决方案有更进一步的改进。无论如何,希望这对于某些人有所帮助,因为这个问题已经困扰了我几个星期。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接