6

在 Angular 中,是否可以有一个线性步进器,其中各个步骤是单独的组件?例如:

<mat-horizontal-stepper [linear]="isLinear">
    <mat-step [stepControl]="firstFormGroup" label="Some Form">
        <first-component></first-component>
    </mat-step>
    <mat-step [stepControl]="secondFormGroup" label="Another Form">
        <second-component></second-component>
    </mat-step>
    <mat-step [stepControl]="thirdFormGroup" label="Review">
        <third-component></third-component>
    </mat-step>
</mat-horizontal-stepper>

matStepperNext当我尝试这个时,我在点击按钮时收到以下错误:

TypeError: Cannot read property 'invalid' of undefined.

4

4 回答 4

6

您可以使用子表单来解决它。实际上,几个月前我在 Angular-UP 会议上发表了一篇关于它的演讲: https ://www.youtube.com/watch?v=sb7tgsNF2Jk

这个想法,一般来说,是在子组件中创建表单,使用 DI 注入 controlContainer 并将本地表单设置为 controlContainer 表单。

子组件:

 @Component({
  selector: 'app-company-info',
  templateUrl: './company-info.component.html',
  styleUrls: ['./company-info.component.scss'],
  viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class CompanyInfoComponent implements OnInit {

  form: FormGroup;
  constructor(
    private ctrlContainer: FormGroupDirective,
    private fb: FormBuilder) { }

  ngOnInit() {

    this.form = this.ctrlContainer.form;

    this.form.addControl('company',
      this.fb.group({
        'companyName': this.fb.control(null, [Validators.required]),
        'numOfEmployees': this.fb.control(null, [Validators.required])});

  }

}

父组件 (html):

<mat-horizontal-stepper [linear]="isLinear" #stepper>
  <mat-step [stepControl]="companyInfo">
    <ng-template matStepLabel>Fill out your name</ng-template>

    <form [formGroup]="companyInfo">
      <app-company-info></app-company-info>
    </form>

    <div>
      <button mat-button matStepperNext>Next</button>
    </div>
  </mat-step>
</mat-horizontal-stepper>

父组件 (ts):

export class WizardComponent implements OnInit {

  isLinear = true;
  companyInfo: FormGroup;

  constructor(private _formBuilder: FormBuilder) {

  }

  ngOnInit() {

    this.companyInfo = this._formBuilder.group({
    });

  }

}
于 2019-03-16T14:15:49.207 回答
5

这是对我有用的解决方案。

<mat-horizontal-stepper [linear]="true" #stepper>
  <mat-step [stepControl]="selectAdvType">
    <ng-template matStepLabel>
      <div class="text-center">
        <mat-icon>queue_play_next</mat-icon><br /><span>Select Adv Type</span>
      </div>
    </ng-template>
    <app-advertisement-type></app-advertisement-type>
  </mat-step>
  <mat-step [stepControl]="selectAdvType">
    <ng-template matStepLabel>
      <div class="text-center">
        <mat-icon>directions_car</mat-icon><br /><span>Select Car</span>
      </div>
    </ng-template>
    <app-select-car-adv></app-select-car-adv>
  </mat-step>
  <mat-step>
    <ng-template matStepLabel>
      <div class="text-center">
        <mat-icon>description</mat-icon><br /><span>Select Features</span>
      </div>
    </ng-template>
    <div>
      <button mat-button matStepperPrevious>Back</button>
      <button mat-button (click)="stepper.reset()">Reset</button>
    </div>
  </mat-step>
</mat-horizontal-stepper>

父 Ts 文件

@Component({
  selector: 'app-customer.create.advertisement',
  templateUrl: './customer.create.advertisement.component.html',
  styleUrls: ['./customer.create.advertisement.component.scss']
})
export class CustomerCreateAdvertisementComponent implements OnInit {
  isLinear = false;
  selectAdvType: FormGroup;
  constructor(private _formBuilder: FormBuilder) { }
  ngOnInit() {
    this.selectAdvType = this._formBuilder.group({
      firstCtrl: ['', Validators.required]
    });
  }
}

子组件

<form [formGroup]="firstFormGroup">
    <ng-template matStepLabel>Fill out your name</ng-template>
    <mat-form-field>
        <input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
    </mat-form-field>
    <div>
        <button mat-button matStepperNext>Next</button>
    </div>
</form>


@Component({
  selector: 'app-advertisement-type',
  templateUrl: './advertisement-type.component.html',
  styleUrls: ['./advertisement-type.component.scss']
})
export class AdvertisementTypeComponent implements OnInit {
  firstFormGroup: FormGroup;
  constructor(private _formBuilder: FormBuilder) { }

  ngOnInit() {
    this.firstFormGroup = this._formBuilder.group({
      firstCtrl: ['', Validators.required]
    });
  }

}
于 2018-11-27T03:40:43.200 回答
2

改进@eliran-eliassy 答案和@christian-steinmeyer 问题。

父组件.ts

  export class ParentComponent implements OnInit {

  isLinear = true;
  companyInfo: FormGroup;

  constructor(private _formBuilder: FormBuilder) {

  }

  ngOnInit() {

    this.companyInfo = this._formBuilder.group({
    });

  }

}

父组件.html

<mat-horizontal-stepper [linear]="isLinear" #stepper>
    <mat-step [stepControl]="companyInfo">
        <form [formGroup]="companyInfo">
            <ng-template matStepLabel>Fill out your name</ng-template>
            <app-company-info></app-company-info>
        </form>
        <div>
            <button mat-button matStepperNext>Next</button>
        </div>
    </mat-step>
</mat-horizontal-stepper>

Child.Component.ts -> 这是子表单

export class ChildComponent implements OnInit {
  form: FormGroup;
  subForm: FormGroup;
  constructor(
    private ctrlContainer: FormGroupDirective,
    private fb: FormBuilder
  ) {}

  ngOnInit() {
    this.subForm = this.fb.group({
      companyName: [null, [Validators.required]],
      numOfEmployees: [null, [Validators.required]]
    });
    
    this.form = this.ctrlContainer.form;
    this.form.addControl("company", this.subForm);
  }
}

Child.Component.html

<div [formGroup]="subForm">
    <mat-form-field appearance="outline">
        <input matInput placeholder="Your Company Name" formControlName="companyName">
  </mat-form-field>
</div>

在stackblitz上查看此解决方案

于 2020-11-04T00:09:47.803 回答
0

好的,我想我看到了一些问题:

<mat-horizontal-stepper [linear]="isLinear">
  <mat-step [stepControl]="foodFormGroup">
    <food-selection></food-selection>
  </mat-step>
  <mat-step [stepControl]="pieFormGroup">
    <pie-selection></pie-selection>
  </mat-step>
</mat-horizontal-stepper>

foodFormGrouppieFormGroup需要在您的 strong-choice.component.ts文件中定义(顺便说一句,在您的示例代码中拼写错误)

这是一个示例(来自文档),它可能看起来如何:

import {Component} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';

/**
 * @title Stepper overview
 */
@Component({
  selector: 'stepper-overview-example',
  templateUrl: 'stepper-overview-example.html',
  styleUrls: ['stepper-overview-example.css']
})
export class StepperOverviewExample {
  isLinear = false;
  firstFormGroup: FormGroup;
  secondFormGroup: FormGroup;

  constructor(private _formBuilder: FormBuilder) { }

  ngOnInit() {
    this.firstFormGroup = this._formBuilder.group({
      firstCtrl: ['', Validators.required]
    });
    this.secondFormGroup = this._formBuilder.group({
      secondCtrl: ['', Validators.required]
    });
  }
}

另外,我在您的示例中没有看到 module.ts 文件。那是您想要导入 @angular/material 模块的地方,而不是在组件文件中。

我建议只给 Angular Material 文档一次。 https://material.angular.io/components/stepper/overview

于 2017-11-16T16:56:17.270 回答