Praveen M P
Praveen M P

Reputation: 11614

Dynamic form validation using angular 2

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

Answers (2)

Gopherine
Gopherine

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

Garth Mason
Garth Mason

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

Related Questions