Reputation: 3209
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.
Upvotes: 12
Views: 24947
Reputation: 1879
Here is how you can have full control on this. Proven, working. for "@angular/cdk": "8.2.3"
, I'm not sure about any future version, maybe they have some built-in feature for this.
Short answer:
Once you've rendered stepper component on the page. You should loop through all steps of the stepper, and override built-in select()
method of each step with your own version.
What you will do in your own version?
currentStepIndex
if you want user to go to the new stepLong answer:
HTML:
<mat-horizontal-stepper [selectedIndex]="selectedStepIndex" #stepper>
In Controller:
@ViewChild('stepper', { static: false }) stepper: MatStepper;
Once your stepper is rendered on the page, you can override select
method like this:
// I personally do this in ngAfterViewInit() method
setTimeout(() => {
this.stepper.steps.forEach((step, idx) => {
step.select = () => {
// Your custom code here
// if you want to change step do execute code below
this.selectedStepIndex = idx;
};
});
});
Upvotes: 6
Reputation: 71
The following approach works for me:
<mat-vertical-stepper [linear]="true" #stepper>
....
</mat-vertical-stepper>
<mat-step [editable]="false" [optional]="false" [stepControl]="desiredServiceFormGroup">
<form [formGroup]="desiredServiceFormGroup">
...
</form>
</mat-step>
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.
<button [disabled]="desiredTarget == null || !paymentAgreed" (click)="createVerification(desiredTarget.targetId, stepper)">NEXT</button>
async createVerification(targetId: number, stepper?: MatStepper) {
this.verification = await this.dataService.createVerification(targetId);
if (stepper !== undefined) {
this.desiredServiceFormGroup.removeControl('x');
stepper.next();
}
}
reset(stepper?: MatStepper) {
this.desiredServiceFormGroup.addControl('x', new FormControl('', [Validators.required]));
stepper.reset();
}
Upvotes: 5
Reputation: 1
You can use completed input decorative (boolean), if step1 is marked as completed then it will go to step2.
Once your service call completed then you can marked completed as "true" then it will go to step2 otherwise it will stay in current step.
Upvotes: 0
Reputation: 37
Here a working suggestion based on the answer of Sam Tsai which is the best I found. I simply use a "step" value is the code and only normal buttons for the navigation.
You can go back and forward only if you have the correct buttons (I mean, this not possible to change the step by clicking on steps). This mean you complete the first step then the second step and so on.
The working example is here: https://stackblitz.com/edit/angular-tznwxe
The trick is to call goStep(x)
where x
is the step starting at 1. You can enhance this by adding a goNext()
and a goPrevious()
which is trivial.
Note the "selectedIndex" of the stepper must be changed with a setTimeout()
: this is known bug discussed here: https://github.com/angular/components/issues/8479#issuecomment-444063732
Upvotes: 1
Reputation: 494
You could try leveraging editable
and completed
attributes on mat-step
.
See https://material.angular.io/components/stepper/overview#editable-step
Without seeing an example, one solution is to:
editable
attribute to false
of all other steps while service call is being mademat-step
and keep this value so you know where the user intended to goeditable
attribute to true
when service call is successful or fails (depending on how you want to handle errors)Upvotes: 0