Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 544
Ankur Akvaliya Avatar asked Apr 03 '19 14:04

Ankur Akvaliya


1 Answers

The following approach works for me:

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

  ....

</mat-vertical-stepper>
  1. 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>
  1. 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 will always be false. When stepControl is false, step is not optional, not editable and stepper is linear. Direct clicks on step headers do not change the current step.

  1. 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>
  1. make your needed operations and when it's done, remove the extra control that makes your form control always invalid. 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();
  }
  
}
  1. If you need to make a reset of stepper, add the extra control to FormControl
reset(stepper?: MatStepper) {
  this.desiredServiceFormGroup.addControl('x', new FormControl('', [Validators.required]));
  stepper.reset();
}
like image 176
Wilson Moises Avatar answered Oct 02 '22 15:10

Wilson Moises