Angular Material Stepper Component For Each Step

2020-02-09 09:37发布

I have a angular material linear stepper each step is a separate angular component containing a form which needs validation

The validation simply just isn't working. I can progress through to the next step without completing the form.

To illustrate what I mean I have created a condensed version on stackblitz.

The main things to look at (I think) is the create-profile.component.html

<mat-horizontal-stepper linear #stepper>
    <mat-step [stepControl]="frmStepOne">
        <ng-template matStepLabel>Step One Details</ng-template>
        <step-one-component></step-one-component>
    </mat-step>
    <mat-step [stepControl]="frmStepTwo">
        <ng-template matStepLabel>Step Two Details</ng-template>
        <step-two-component></step-two-component>
    </mat-step>
    <mat-step [stepControl]="frmStepThree">
        <ng-template matStepLabel>Step Three Details</ng-template>
        <step-three-component></step-three-component>
    </mat-step>
</mat-horizontal-stepper>

And each step-X-component

Here is the stackblitz. https://stackblitz.com/edit/angular-vpoj5j

2条回答
男人必须洒脱
2楼-- · 2020-02-09 10:06

Your stepper and forms components works on different form objects. You need to set super's forms objects in step component's ngONInit()

ngOnInit() {
    super.frmStepTwo = this.formBuilder.group({
        address: ['', Validators.required]
    });

instead

ngOnInit() {
    this.frmStepTwo = this.formBuilder.group({
        address: ['', Validators.required]
    });
查看更多
何必那么认真
3楼-- · 2020-02-09 10:19

The problem is in your CreateProfileComponent:

@Component({
    selector: 'create-profile-component',
    templateUrl: './create-profile.component.html'
})
export class CreateProfileComponent {

    frmStepOne: FormGroup;
    frmStepTwo: FormGroup;
    frmStepThree: FormGroup;

    constructor(private fb: FormBuilder) { }


}

There is no relation between your defined FormGroup's in CreateProfileComponent and your stepper components. You tried to extend every StepComponent with CreateProfileComponent, but with this approach every StepComponent holds his own instance of CreateProfileComponent and so there own FormGroup's declaration.

To solve your problem you can declare template variables for every StepComponent in your html (starting with #) and pass the formControl to [stepControl]:

<mat-horizontal-stepper linear #stepper>
    <mat-step [stepControl]="step1.frmStepOne">
        <ng-template matStepLabel>Step One Details</ng-template>
        <step-one-component #step1></step-one-component>
    </mat-step>
    <mat-step [stepControl]="step2.frmStepTwo">
        <ng-template matStepLabel>Step Two Details</ng-template>
        <step-two-component #step2></step-two-component>
    </mat-step>
    <mat-step [stepControl]="step3.frmStepThree">
        <ng-template matStepLabel>Step Three Details</ng-template>
        <step-three-component #step3></step-three-component>
    </mat-step>
</mat-horizontal-stepper>

Or you leave your html as it is and work with ViewChild() (My preferred approach).

@Component({
    selector: 'create-profile-component',
    templateUrl: './create-profile.component.html'
})

export class CreateProfileComponent {

    @ViewChild(StepOneComponent) stepOneComponent: StepOneComponent;
    @ViewChild(StepTwoComponent) stepTwoComponent: StepTwoComponent;
    @ViewChild(StepTwoComponent) stepThreeComponent: StepThreeComponent;

    get frmStepOne() {
       return this.stepOneComponent ? this.stepOneComponent.frmStepOn : null;
    }

    get frmStepTwo() {
       return this.stepTwoComponent ? this.stepTwoComponent.frmStepTwo : null;
    }

    get frmStepThree() {
       return this.stepThreeComponent ? this.stepThreeComponent.frmStepThree : null;
    }

}

Either way there is no need to extend your StepComponents with CreateProfileComponent and it doesn't make any sense.

@Component({
    selector: 'step-x-component',
    templateUrl: './step-x.component.html',
})
export class StepXComponent {

    public formStepX: FormGroup;

    constructor(private formBuilder: FormBuilder) {
    }

    ngOnInit() {
        this.frmStepX = this.formBuilder.group({
            name: ['', Validators.required]
        });

    }

}
查看更多
登录 后发表回答