Struggling with incorporating *ngIf and ngFormModel in form validation?
Here's the scenario: based on user input, you need to hide or disable certain fields in the form. However, if these inputs are visible, they must be validated.
When simple validation suffices, there are workarounds:
- To enforce required input, use
ngControl
andrequired
- For specific format requirements, the
pattern
attribute can be utilized outside Angular for functionality.
For more intricate validations, attempting to combine ngControl
with ngFormModel
for custom checks is the goal. Drawing inspiration from code snippets found on:
How to add form validation pattern in angular2 (and associated links)
Angular2 Forms :Validations, ngControl, ngModel etc
The provided code snippet looks like this:
HTML
<div>
<h1>Issue Overview</h1>
<form (ngSubmit)="submitForm()" #formState="ngForm" [ngFormModel]="myForm">
<div class="checkbox">
<label>
<input type="checkbox" [(ngModel)]="model.hideField" ngControl="hideField"> Is the input below useless for you ?
</label>
</div>
<div *ngIf="!model.hideField">
<div class="form-group">
<label for="optionalField">Potentially irrelevant field </label>
<input type="text" class="form-control" [(ngModel)]="model.optionalField" ngControl="optionalField" required #optionalField="ngForm">
<div [hidden]="optionalField.valid || optionalField.pristine" class="alert alert-warning">
This input must go through myCustomValidator(), so behave.
</div>
</div>
</div>
<button type="submit" class="btn btn-primary" [disabled]="!formState.form.valid">I can't be enabled without accessing the input :(</button>
<button type="submit" class="btn btn-default">Submit without using form.valid (boo !)</button>
</form>
</div>
Typescript
import {Component, ChangeDetectorRef, AfterViewInit } from 'angular2/core';
import {NgForm, FormBuilder, Validators, ControlGroup, FORM_DIRECTIVES} from 'angular2/common';
@Component({
selector: 'accueil',
templateUrl: 'app/accueil.component.bak.html',
directives:[FORM_DIRECTIVES],
providers: [FormBuilder]
})
export class AccueilComponent implements AfterViewInit {
private myForm: ControlGroup;
model: any;
constructor(fb: FormBuilder, cdr: ChangeDetectorRef) {
this.cdr = cdr ;
this.model = {} ;
this.myForm = fb.group({
"hideField": [false],
"optionalField": [this.model.optionalField, Validators.compose([this.myCustomValidator])]
});
}
ngAfterViewInit() {
// Necessary to prevent "Expression has changed after it was checked" error
this.cdr.detectChanges();
}
submitForm(){
alert("Submitted !");
}
myCustomValidator(optionalField){
// Replace "true" by "_someService.someCheckRequiringLogicOrData()"
if(true) {
return null;
}
return { "ohNoes": true };
}
}
Even when an input is hidden with *ngIf, referencing the control in the constructor causes issues. This leads to difficulty in utilizing [disabled]="!formState.form.valid", as myForm
remains INVALID due to the setup.
Is achieving the desired functionality possible within Angular 2? While this may be a common scenario, figuring out the solution can be tricky with existing knowledge.
Thank you!