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

6
  • @GabrieleB-David form fields are loaded in the subsection template. I am passing fields as input to the template Commented Mar 16, 2017 at 14:18
  • 1
    I believe it's because your inputs are in a child component. You have to give the parent component a way of seeing if all the fields are filled. Why not put the whole form in one component? Commented Mar 16, 2017 at 14:20
  • @GabrieleB-David you are correct. (assume) i am using reusable component to create the form fields. So parent form element not having hold on child form elements? Commented Mar 16, 2017 at 14:22
  • 1
    Then you could use an @Output event that triggers when all the forms are filled in the child. Commented Mar 16, 2017 at 14:24
  • maybe this answer will help. stackoverflow.com/questions/34980344/… Commented Mar 16, 2017 at 14:45

2 Answers 2

1

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>
Sign up to request clarification or add additional context in comments.

Comments

1

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>

2 Comments

@PraveenMP I updated my answer I see that this was not working . when using !loginForm.invalid the button used to disable but due to reverse condition it was disabling the button completely even after filling the form I dont know what is causing it. But the above works if you move your forms section completely inside one component and move that comonent to another.
Yes i have understood the way you are implemented and it works. But i don't want to keep subsection code in the main component.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.