Reputation: 11614
I am working on angular 2 application and creating the form fields dynamically(using json) in a subsection template.
I wanted to disable submit button when the form is invalid.
<h1>Form Validation</h1>
<div >
<form #loginForm="ngForm">
<subsection [question]="fieldsData"></subsection>
<button type="submit" [disabled]="!loginForm.form.valid">Submit</button>
</form>
</div>
Sub section as it follows
<div *ngFor="let data of question">
<label> {{data.displayName}}</label>
<input type="data.dataType" name="data.fieldId" [(ngModel)]="data.fieldValue" required name="data.fieldId" #name="ngModel">
<div *ngIf="name.errors && (name.dirty || name.touched)" class="alert alert-danger">
<div [hidden]="!name.errors.required">
Name is required
</div>
</div>
<br><br>
I have a requirement where submit button should be enabled after all the required fields are filled
Created plunker link Here
Upvotes: 2
Views: 3083
Reputation: 1111
question.component.html
<form #loginForm="ngForm">
<div *ngFor="let data of question">
<label> {{data.displayName}}</label>
<input type="data.dataType" [(ngModel)]="data.fieldValue" required name="data.fieldId" #name="ngModel">
<div *ngIf="name.errors && (name.dirty || name.touched)" class="alert alert-danger">
<div [hidden]="!name.errors.required">
{{data.displayName}} is required
</div>
</div>
<br><br>
</div>
<button type="submit" [disabled]="loginForm.invalid">Submit</button>
</form>
The above disables the submit button you can use the above to activate using *ngIf. You can also use the above as !loginForm.valid.
app.component.html
<h1>Form Validation</h1>
<subsection [question]="fieldsData"></subsection>
Upvotes: 1
Reputation: 8011
Based on your plunkr I think you'd be better served using a reactive form rather than the template driven form approach you have described, as you are defining your form fields in a model anyway (the fieldsData
array defined in AppComponent
).
The current template approach isn't giving you the validation behaviour you want as the input
fields in the sub-component are not participating in the wider form - if you debug loginForm.value
you will see that the name fields are not part of the form - meaning that if you submit the form, the form will not contain the data entered in those fields.
An alternative is to make the sub-component participate in the form by implementing ControlValueAccessor
as described here but this adds complexity you may not need.
A simpler way would be (1) use reactive forms or (2) don't use a nested subsection component at all.
<form #loginForm="ngForm">
<div *ngFor="let data of fieldsData">
<label> {{data.displayName}}</label>
<input type="data.dataType" [(ngModel)]="data.fieldValue" required [name]="data.fieldId" #name="ngModel">
<div *ngIf="name.errors && (name.dirty || name.touched)" class="alert alert-danger">
<div [hidden]="!name.errors.required">
{{data.displayName}} is required
</div>
</div>
</div>
<button type="submit" [disabled]="!loginForm.form.valid">Submit</button>
Form contains: {{loginForm.value | json }}
</form>
Upvotes: 1