Reputation: 1939
I was trying to implement what seemed to be a straightforward form validation routine following this walk-through on my ionic 2 projects.
In my controller's constructor I used the FormBuilder
like this to make a formGroup:
this.form = formBuilder.group({
date: ['', Validators.required],
client: ['', Validators.required]
});
And then in the template I added formControllerName
attribute to relevant elements like this:
<ion-select formControlName="client" [(ngModel)]="clientId">
And bound the root element to the 'formGroup` like this:
<ion-content [formGroup]="form">
This fails with the following error message:
ngModel cannot be used to register form controls with a parent formGroup directive. Try using formGroup's partner directive "formControlName" instead. Example:
<div [formGroup]="myGroup"> <input formControlName="firstName"> </div> In your class: this.myGroup = new FormGroup({ firstName: new FormControl() }); Or, if you'd like to avoid registering this form control, indicate that it's standalone in ngModelOptions: Example: <div [formGroup]="myGroup"> <input formControlName="firstName"> <input [(ngModel)]="showMoreControls" [ngModelOptions]="{standalone: true}"> </div>
As suggested by the error message, as well as this StackOverflow thread I added [ngModelOptions]="{standalone: true}"
to my inputs but it came back with another error message:
Template parse errors: Can't bind to 'ngModelOptions' since it isn't a known property of 'ion-select'.
Upvotes: 3
Views: 3996
Reputation: 4353
In angular2 you can choose to either use the "old" (more AngularJS-y) template-driven way, by using [(ngModel)]
to create two-way bindings with your component variables:
Component:
private clientId: string;
Template:
<form>
<input [(ngModel)]="clientId" required />
</form>
If I got facts together, this will behind-the-scenes create a FormGroup
instance for the <form>
element, and a FormControl
instance for each input in it. The required directive will then apply a validator on it and trigger validation (and for example apply ng-valid/invalid accordingly).
Using this approach you can grab the value simply using clientId
.
Using the model-driven (or "reactive") approach is by defining the form's "schema" using FormBuilder
or simply creating instances of FormGroup
and FormControl
...
It would look something like this:
Component:
private form: FormGroup;
ngOnInit() {
this.form = new FormGroup({
clientId: new FormControl('', [Validators.required])
});
}
Template:
<form [formGroup]="form">
<input formControlName="clientId" />
</form>
In this case, if you want the entire form's value, you'd access (this.)form.value
which in this example will return an object like this:
{ clientId: "whatever" }
Or if you only want the inner control's value, grab (this.)form.controls['clientId'].value
.
Hope I made things clearer and not worse :)
EDIT:
Using the latter approach means you can access an Observable
of the FormControl
and do some interesting things, for example:
let debouncedInput$ = this.form.control['clientId'].valueChanges.debounceTime(1000);
Upvotes: 6