Angular material stepper before-selection-change & prevent step-change for some condition

angularangular-cdkangular-material-7angular-material-stepper

I am using linear mat-stepper.

It works fine with next. I do api call & if it's success then i call stepper-next event instead of using matStepperNext directive.

Now when user fills all data on step 1 & directly click on some other step in header of next(or any other on edit record mode) then it will redirect to next step since form is valid.

I want to do service call before that & prevent step-change until service call is successful then only it should redirect to next step otherwise it shouldn't.

I can't find any method to implement this functionality in doc.

Can anyone suggest me what to do. I don't want to disable header click.

Best Answer

I'm not sure if this is the best mode, but it works for me. Suggestions are welcome.

1) Make mat-stepper linear

<mat-vertical-stepper [linear]="true" #stepper>

  ....

</mat-vertical-stepper>

2) Make steps not editable, not optional and associate a stepControl with a FormGroup

  <mat-step [editable]="false" [optional]="false" [stepControl]="desiredServiceFormGroup">

    <form [formGroup]="desiredServiceFormGroup">

      ...

    </form>

  </mat-step>

3) add controls to your FormGroup for your form items described in HTML and add a extra control, for an inexistent form control on your html code (in this example, I added the control called 'x', inexistent in my html code)

ngOnInit() {

  this.desiredServiceFormGroup = this.formBuilder.group({
    desiredTarget: [ '', Validators.required],
    paymentAgreed: ['', Validators.required],

    ...

    x: ['', Validators.required]
  });

}

With this extra validator, your stepControl always will be false. When stepControl is false, step is not optional, not editable and stepper is linear, direct clicks on step headers not change the current step.

5) button will not be associated with formControl (at that case, it will be always disabled). In my case, I verify each Form item manually

<button [disabled]="desiredTarget == null || !paymentAgreed" (click)="createVerification(desiredTarget.targetId, stepper)">NEXT</button>

6) make your needed operations and when it's be done, remove the extra control that makes always invalid your form control, ando go programmatically to next step.

async createVerification(targetId: number, stepper?: MatStepper) {

  this.verification = await this.dataService.createVerification(targetId);

  if (stepper !== undefined) {
    this.desiredServiceFormGroup.removeControl('x');
    stepper.next();
  }

}

7) if you need make a reset of stepper, remind add the extra control to FormControl

reset(stepper?: MatStepper) {
  this.desiredServiceFormGroup.addControl('x', new FormControl('', [Validators.required]));
  stepper.reset();
}
Related Topic