How does MatStepper triggers the error state for a step?
Asked Answered
B

1

6

I'm implementing a mat-horizontal-stepper in one of my components and I'm trying to get the error state to display on a step if I move from it while the [completed] property is false but this is not happening.

I'm not sure if there's some limitations with working with the completed property or something like that; this is what I have so far:

Component's HTML

<mat-horizontal-stepper linear #auditStepper>
     <mat-step label="Choose a Company" [completed]="selectionClient.selected.length > 0">
     </mat-step>

     <mat-step label="Select a PPC Account" errorMessage="Select an Account" [completed]="selectionPPC.selected.length > 0">
     </mat-step>

     <mat-step label="Set Your Targets">  
     </mat-step>
</mat-horizontal-stepper>

Component's TS

@Component({
  selector: 'app-new-audit',
  templateUrl: './new-audit.component.html',
  styleUrls: ['./new-audit.component.scss'],
  providers: [
    {
      provide:  STEPPER_GLOBAL_OPTIONS,
      useValue: { showError: true }
    }
  ]
})

In the code above I'm only providing the important stuff; but if I'm following the Angular Material docs correctly, what I need to do is add the providers to the component (or my main App Module) and that's it?

So if I get to step 2 for example but keep the completed condition false and then move to another step it should trigger the error because the step is no longer active but not completed as well.

I'm just trying to understand how everything works since I'm not using reactive forms or any forms actually for this stepper since I'm working with a MatTable instead; I just need the user to select a row from the table (via MatTable's selection feature) and if the selection array has one element then I can consider the step as "complete" and enable moving to the next step.

Stackblitz Demo https://stackblitz.com/edit/angular-khyu8u

EDIT:

The error state works perfectly fine if I use a FormGroup and the [stepControl] property for the step, but I need it without a form.

Bailor answered 30/8, 2019 at 17:59 Comment(3)
Can you please reproduce this issue in stackblitz?Slotnick
@Slotnick sure! I'll try to add it in a momentBailor
@Slotnick added the stackblitz, it's very barebones but I think I included the necessary stuff; conditions, properties, etcBailor
S
12

There is dedicated method that describes what is required in order an error to be displayed:

private _getDefaultIndicatorLogic(step: CdkStep, isCurrentStep: boolean): StepState {
  if (step._showError && step.hasError && !isCurrentStep) {
    return STEP_STATE.ERROR;
  }
  • step._showError comes from STEPPER_GLOBAL_OPTIONS you defined in providers
  • step.hasError includes the most interesting part

Here are all definitions:

@Input()
get hasError(): boolean {
  return this._customError == null ? this._getDefaultError() : this._customError;
}

set hasError(value: boolean) {
  this._customError = coerceBooleanProperty(value);
}

private _getDefaultError() {
  return this.stepControl && this.stepControl.invalid && this.interacted;
}

As you can see hasError returns true if

1) we have stepControl with invalid state and the current step is interacted

2) we pass hasError Input props which return true

  • !isCurrentStep means that an error will be displayed only if you're on other steps

So you can pass hasError property to the step with your custom logic, e.g.:

<mat-step ... #step [hasError]="step.interacted" 

Forked Stackblitz

Slotnick answered 1/9, 2019 at 19:28 Comment(2)
hey! thank you a lot, this does work perfectly and your explanation was really clear! you saved me :)Bailor
Is there any way to put the current step in error instead of moving to next step? Since I am using the step as an activity I want to show the step in error if Http call returns error for that step.Dawson

© 2022 - 2024 — McMap. All rights reserved.