In Angular-12, I am implementing Material Stepper. And it has two (2) steps:
Component:
export class SignupCompanyComponent implements OnInit {
isLinear = true;
isLoading = false;
companySetupForm!: FormGroup;
companyForm!: FormGroup;
idForm!: FormGroup;
ngOnInit() {
this.companyForm = this.fb.group({
companyName: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(100)]]
});
this.idForm = this.fb.group({
registrationNumber: ['', [Validators.required, Validators.maxLength(100)]],
});
}
get fc() {
return this.companyForm.controls;
};
get fi() {
return this.idForm.controls;
};
onSubmit() {}
}
HTML:
<mat-horizontal-stepper [linear]="isLinear" #stepper labelPosition="bottom">
<mat-step [stepControl]="companyForm">
<form [formGroup]="companyForm">
<ng-template matStepLabel matStepperIcon="phone">Company Info</ng-template>
<div class="col-12 col-md-12">
<div class="form-group">
<label for="name">Company Name:<span style="color:red;">*</span></label>}
<input type="text" formControlName="companyName" placeholder="Company Name" class="form-control" required/>
</div>
<div *ngIf="fc.companyName.touched && fc.companyName.invalid">
<div *ngIf="fc.companyName.hasError('required')">
<div class="text-danger">
Company Name is required!
</div>
</div>
<div *ngIf="fc.companyName.hasError('minlength')">
<div class="text-danger">
Company Name cannot be less than 3 characters!
</div>
</div>
<div *ngIf="fc.companyName.hasError('maxlength')">
<div class="text-danger">
Company Name cannot be more than 100 characters!
</div>
</div>
</div>
</div>
<div class="card-footer">
<button mat-raised-button color="primary" matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="idForm">
<form [formGroup]="idForm">
<ng-template matStepLabel>Company ID</ng-template>
<div class="col-12 col-md-4">
<div class="form-group">
<label for="registration_number">Registration Number:<span style="color:red;">*</span></label>
<input type="text" formControlName="registrationNumber" placeholder="Registration Number" class="form-control" required/>
</div>
<div *ngIf="fi.registrationNumber.touched && fi.registrationNumber.invalid">
<div *ngIf="fi.registrationNumber.hasError('required')">
<div class="text-danger">
Company Reg. No. is required!
</div>
</div>
<div *ngIf="fi.registrationNumber.hasError('maxlength')">
<div class="text-danger">
Company Reg. No. cannot be more than 100 characters!
</div>
</div>
</div>
</div>
<div class="card-footer">
<button mat-raised-button color="black" matStepperPrevious>Back</button>
<button mat-raised-button color="success" [disabled]="isLoading" type="submit" (click)="onSubmit()">
<span *ngIf="isLoading" class="spinner-border spinner-border-sm mr-1"></span>
Submit
</button>
<button mat-raised-button color="warn" (click)="stepper.reset()">Reset</button>
</div>
</mat-step>
</mat-horizontal-stepper>
When each formControl is touched, the Material Stepper works fine. It displays the error immediately. But when Next Button is clicked no data is filled in Step1 (companyForm), though it didn't move to the next step or form, but no error is displayed.
I want it to validate each step and display as it is done when each form control is touched.
How do I achieve this?
Thanks
Material doesn't seem to mark the form as touched, so i'd rebind the button:
<button mat-raised-button color="primary" (click)="onFirstStepDone()">Next</button>
in the component, you'll need a reference to the stepper:
@ViewChild('stepper') stepper: MatHorizontalStepper;
onFirstStepDone() {
if(!this.companyForm .valid) {
// this should make all invalid fields light up in red
this.companyForm.markAllAsTouched();
return;
}
this.stepper.next();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With