I am using an Angular 2+ wizard component (I'm on Angular 6) that I forked into my project and did a lot of template and styling customizations to. Unfortunately the one I chose doesn't support the canExit functionality found in other wizards, so I am trying to add it. It has the ability to validate the form in the step, so I've usually been able to just add another custom validation function when I need to do more than simple field validation like so:
<custom-wizard>
<wizard-step [title]='Step 1' [isValid]='step1Form.valid && validateStep1()'>
<form>....
The problem is this gets called repeatedly, due to Angular's watching and change detection I assume. Normally that's not a problem but I want to do a server-side validation only once when they hit Next. Having it called repeatedly is a non-starter.
So I figure I needed to pass a callback function as a parameter to the child wizard-step component:
<custom-wizard>
<wizard-step [title]='Step 1' [isValid]='step1Form.valid' [canExit]='validateStep1()'>
<form>....
In the parent component, I created my validation function:
validateStep1(){
console.log('calling server...');
// assume this is a server-side call, returning true/false
return serverValidationPassed();
}
In the wizard-step component I added:
@Input() canExit: boolean = true;
In the custom-wizard, I check if this callback fails and if so prevent the normal step change:
public next(): void {
if(!this.activeStep.canExit){
console.log('failed!');
return;
}
else {
//proceed to next step as usual
}
}
The problem is the validation is still called many times, I was right back where I started! I read about using an @Output to pass in functions instead, so I tried this approach:
<custom-wizard>
<wizard-step [title]='Step 1' [isValid]='step1Form.valid' (canExit2)='validateStep1()'>
<form>....
And in the wizard-step:
@Output() canExit2: EventEmitter<any> = new EventEmitter<any>();
And in the wizard's next function:
public next(): void {
if(!this.activeStep.canExit2.emit()){
console.log('failed!');
return;
}
else {
//proceed to next step as usual
}
}
The validate step is only called once now, nice. But even when the validateStep1 passes, I get a failure on the if check. I believe it's because an emit doesn't return anything, but rather broadcasts. This is new territory for me. Can someone point out what I'm doing wrong here and how I can perform this extra validation?