4

We have a linear mat-horizontal-stepper now we want to show a MatSnackBar when the user tries to proceed an forgot a required field.

CdkStepper seems to call _anyControlsInvalidOrPending silently and returns if any input is not valid.

Does anybody have an idea how to detect this event?

It must be detected when calling stepper.next(), stepper.previous() and step.select()

Rafael
  • 1,281
  • 2
  • 10
  • 35
wutzebaer
  • 14,365
  • 19
  • 99
  • 170

3 Answers3

4

A dirty solution would be

  ngAfterViewInit() {
    // when clicking on the step header
    this.stepper._steps.forEach((step) => {
      this.addPriorValidyCheckToFunction(step, 'select');
    });
    // when calling previous and next function
    this.addPriorValidyCheckToFunction(this.stepper, 'next');
    this.addPriorValidyCheckToFunction(this.stepper, 'previous');
  }

  addPriorValidyCheckToFunction(object, functionName) {
    // keep reference to AppComponent
    let self = this;
    // keep reference to original function
    let oldFunction = object[functionName];
    // replace original function
    object[functionName] = function () {
      // remember step before calling the function
      let oldStep = self.stepper.selected;
      // call the original function
      oldFunction.call(object);
      // if step did not change and form is invalid, show the message
      if (oldStep == self.stepper.selected && !self.stepper.selected.stepControl.valid) {
        self.snackBar.open("Fehler", "Bitte überprüfen Sie Ihre Eingaben", {
          duration: 2000,
        });
      }

    };
  }
wutzebaer
  • 14,365
  • 19
  • 99
  • 170
2

You need to add a "linear" attribute

<mat-vertical-stepper linear>

This will disable from navigating to next step if the form is invalid. Then add your validation function on click of the button if form is invalid then you can show alert or snackbar or whatever you want.

Vishal Hulawale
  • 472
  • 5
  • 9
0

If you could show your component and template code that contains the mat-stepper that would really help. However, from your description I believe binding to the selectionChange event would work for you.

In the template that contains the stepper: stepper-example.component.html

<mat-horizontal-stepper #stepper (selectionChange)="onStepChange($event)">
 <!-- your form -->
</mat-horizontal-stepper>

Then in your component: stepper-example.component.ts

import { Component, ViewChild } from '@angular/core';
@Component({
  selector: 'stepper-example',
  templateUrl: './stepper-example.component.html'
})
export class StepperExampleComponent {
@ViewChild('stepper') stepper;


public onStepChange(event): void{
    //Some logic to validate your forms
  }
}
Narm
  • 10,677
  • 5
  • 41
  • 54