Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does MatStepper triggers the error state for a step?

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.

like image 934
IvanS95 Avatar asked Aug 30 '19 17:08

IvanS95


1 Answers

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

like image 50
yurzui Avatar answered Nov 05 '22 09:11

yurzui