Reputation: 1
I have a html page which has 5 in a html page. I want to disable submit button if any validation fails. but I have 2 forms always visible and 3 forms are hidden. and these 3 forms are shown based on some condition only. so there can be 2, 3, 4 or 5 forms visible.
So If I try the below code, it does not work properly, because form3,form4 and form5 are not visible.
<form class="form-horizontal" role="form" name="form1">
<form class="form-horizontal" role="form" name="form2">
<form class="form-horizontal" role="form" name="form3" *ngIf="condition1">
<form class="form-horizontal" role="form" name="form4" *ngIf="condition2">
<form class="form-horizontal" role="form" name="form5" *ngIf="condition3">
<button type="button" class="btn btn-primary" (click)="onSubmitBtnClick()" [disabled]="!form1.form.valid || !form2.form.valid || !form3.form.valid || !form4.form.valid || !form5.form.valid">Save</button>
So How I can handle this case.
Error:
Cannot read property 'form' of undefined
Upvotes: 1
Views: 364
Reputation: 3196
Use angular's reactive forms + nested FormGroups
: https://angular.io/guide/reactive-forms#nested-formgroups
In general, when page is loaded your form should have 3 groups (1 per "form"). Declare form as:
this.form = this.fb.group({
subForm1: this.fb.group({
subForm1_field1: ['', Validators.required ],
subForm1_field2: ['', Validators.required, Validators.min(5) ],
}),
subForm2: this.fb.group({
subForm2_field1: '',
subForm2_field2: ['', Validators.required, Validators.max(10) ],
}),
subForm3: this.fb.group({
subForm3_field1: '',
})
});
So finally for submit button you can use only parent form to get validation status (it will be false
if any field from any nested form group is invalid). HTML code:
<input type="checkbox" (ngModel)="onShowSubForm3()"/><label>Show Form3</label>
<form [formGroup]="form">
<div class="form-horizontal"><!-- your inputs goes here for subForm1 --></div>
<div class="form-horizontal"><!-- your inputs goes here for subForm2 --></div>
<div class="form-horizontal" *ngIf="showSubForm3"><!-- your inputs goes here for subForm3 --></div>
</form>
<button type="button" (click)="submitSubForm1()" [disabled]="!form.get("subForm3").valid">Send 1</button> <!-- is disabled only if any field from `subForm3` is invalid -->
<button type="button" (click)="submitAllForms()" [disabled]="!form.valid">Send All</button> <!-- is disabled if any field is invalid -->
Code to send form/send 1 subForm:
submitAllForms(){
let formValue = this.form.value();
/*formValue = {
subForm1: {
subForm1_field1: "val1-1",
subForm1_field2: "val1-2",
},
subForm2: {
subForm2_field1: "val2-1",
subForm2_field2: "val2-2",
},
};*/
this.http.post("/url", {data: formValue});
}
submitSubForm1(){
let subForm1Value = this.form.get["subForm1"].value;
/*subForm1Value = {
subForm1_field1: "val1-1",
subForm1_field2: "val1-2",
};*/
this.http.post("/url", {data: subForm1Value});
}
Each time you need to show/hide new sub form - update this.form
(you may want to store all fields but update Validators
only).
showSubForm3: boolean = false;
onShowSubForm3(value){
this.showSubForm3 = value;
//THIS CODE CAN BE OPTIMIZED TO UPDATE ENTIRE `FormGroup` WITH NEW VALIDATORS
let field = this.form.controls["subForm3.subForm3_field1"];
if(value){
field.setValidators(Validators.compose([Validators.required]));
}else{
field.setValidators(Validators.compose([]));
}
field.updateValueAndValidity();
}
Upvotes: 0
Reputation: 8911
You can accomplish this. The way I did it without triggering a bunch of change detection already checked errors is to use a singular function in my component to check form validation and whether the button should be disabled. This required me using ViewChild
s for each of my forms. It looks something like this:
Component:
showForm1 = true;
showForm2 = true;
showForm3 = false;
showForm4 = false;
showForm5 = false;
@ViewChild('form1') form1: NgForm;
@ViewChild('form2') form2: NgForm;
@ViewChild('form3') form3: NgForm;
@ViewChild('form4') form4: NgForm;
@ViewChild('form5') form5: NgForm;
shouldDisable() {
if (this.showForm1 && this.form1 && !this.form1.valid) {
return true;
}
if (this.showForm2 && this.form2 && !this.form2.valid) {
return true;
}
if (this.showForm3 && this.form3 && !this.form3.valid) {
return true;
}
if (this.showForm4 && this.form4 && !this.form4.valid) {
return true;
}
if (this.showForm5 && this.form5 && !this.form5.valid) {
return true;
}
return false;
}
Template:
<form #form1="ngForm" *ngIf="showForm1"></form>
<form #form2="ngForm" *ngIf="showForm2"></form>
<form #form3="ngForm" *ngIf="showForm3"></form>
<form #form4="ngForm" *ngIf="showForm4"></form>
<form #form5="ngForm" *ngIf="showForm5"></form>
<button type="button" class="btn btn-primary" (click)="onSubmitBtnClick()" [disabled]="shouldDisable()">Save</button>
Hope that helps.
Upvotes: 1