In your app.module:
import { FormsModule } from '@angular/forms';
Now when angular detects a <form>
will create a javascript object representation of your form.
name
and marking them with ngModel
:<input type="text" ngModel name="username">
ngForm
, that is the javascript object representation of the form created by Angular) to the <form>
, and pass it to the function you attach to ngSubmit
handler:
<form (ngSubmit)="onSubmit(myForm)" #myForm="ngForm">
onSubmit(form: NgForm) {
console.log(form);
}
If we inspect the object in the consol:
value
form controls in key/value pairscontrols
has representations of each input, with its own propertiesdirty
tells if we have changed anything in the formtouched
if we have interactedinvalid
/ valid
@ViewChild
we can access an element holding a local reference:export class AppComponent {
@ViewChild('myForm') signupForm: NgForm; //access the local reference and store it in a variable of type NgForm
//this gives you access to the form object without having to submit,
//this is specially useful if you need to access the form earlier to the point you submit it
onSubmit() {
console.log(this.signupForm);
// use the form data
this.user.username = this.signupForm.value.userData.username;
// reset the form
this.signupForm.reset(); //will empty all the inputs and also reset the state (valid, touched etc)
}
}
<input ... required email>
required
is only treated as a selector to take in account when checking if form is valid
email
is not an html attribute, is a directive to make sure is a valid email address.
valid
state is checked at a form
level and at input
level
classes are added to the input
depending on the state:
<input ng-dirty ng-touched ng-invalid>
So you can:
input.ng-touched.ng-invalid {
border: 1px solid red
} //to affect only to inputs that have been touched
disable the submit
button if the form
is not valid
:
<button type="submit" ... [disabled]="!myForm.valid">
//put here the name of your local reference
output validation messages: put a local reference in the input
, and associate this to ngModel
, that will expose us information about the control:
<input ... #email="ngModel">
<p class="help-block" *ngIf="!email.valid && email.touched">Please enter a valid email!</p>
Built-in validator directives in Angular for template driven approach: search for "validator" in the official docs: https://angular.io/api?type=directive - everything marked with "D" is a directive and can be added to your template.
If you need HTML5 native validation (disabled by Angular by default) add ngNativeValidate
to the desired input
ngModel
property binding:defaultQuestion = 'pet';
<select ... [ngModel]="defaultQuestion">
<option value="pet">Your first Pet?</option>
<option value="teacher">Your first teacher?</option>
</select>
answer = '';
<textarea ... [(ngModel)]="answer">
</textarea>
<p>Your reply: {{ answer }}</p>
<div ngModelGroup="userData" #userData="ngModelGroup">
<input ...name="username">
<input ...name="email">
</div>
<p *ngIf="!userData.valid && userData.touched">User data not valid</p>
Output object:
value: {
...
userData: {
usename: ""
email: ""
}
}
and also in controls
:
controls: {
question: FormControl
userData: FormGroup
}
Example: a button than when clicked, will populate the 'username' field.
@ViewChild
:
@ViewChild('myForm') signupForm: NgForm;
So we can:
this.signupForm.setValue({ //allows us to set the value of the whole form. Here we need to pass a javascript object exactly representing our form
userData: {
username: suggestedName,
email: ''
},
secret: 'pet',
});
this.signupForm.form.patchValue({ //important! you have to access .form property and then patchValue method
userData: {
username: suggestedName
}
});