Angular Model Driven Forms
Model driven forms is a new concept in angular 2. In angular 1, all we had was template driven forms which by the way, you can still use in Angular 2.
What is a model driven form?
Before we look at why you would want to use model driven forms, what do we mean by model driven forms?
Architecturally, a form has 4 parts:
- DOM. This is where the form is rendered to!
- Template. This defines how the fields are laid out in the DOM
- Form Model. This defines the fields on the form and some of the associated UI logic such as what the client side validation rules are and what the default values are
- Domain Model. This contains the fields and their values
In angular 1, the form model was hidden from us - angular creates this for us from the template. In angular 2 we can create the form model using FormBuilder. Using FormBuilder in Angular 2 is taking the model driven approach.
Why?
So, why would we want to do this? This sounds like extra work - if angular 1 did this for us, why would we now want to write that code? There are a number of reasons …
- Maintainability. When fields on the form depend on conditions, when the validation for fields depend on conditions or the defaults depend on conditions, it may be easier to read and debug imperative code for this rather than declarative code in the template
- More unit testable. More of the UI logic can now be abstracted and totally independent of the DOM, which makes unit testing easier
- Performance. In angular 1, angular managed the data flow via 2 way bindings which can be slow if you have lots of bindings with large dependency chains. In the model driven approach you can control the flow of data
- Functional Reactive Programming. Controlling the data flow means that you can use functional reactive programming for UI logic.
So, in general, when we are dealing with large complex forms, the model driven approach may be a better approach.
Example
Let’s look at a simple login form as an example. This is an angular 2 login component …
import {
Component,
FORM_DIRECTIVES,
ControlGroup,
FormBuilder,
Validators
} from "angular2/angular2";
@Component({
selector: "my-login",
template: `
<form [ng-form-model]="loginForm" (submit)="login($event)">
<div>
<label for="username">Username</label>
<input
type="text"
id="username"
placeholder="Username"
ng-control="userName"
/>
</div>
<div>
<label for="password">Password</label>
<input
type="password"
id="password"
placeholder="Password"
ng-control="password"
/>
</div>
<button type="submit">Submit</button>
</form>
`,
directives: [FORM_DIRECTIVES]
})
export class LoginComponent {
loginForm: ControlGroup;
constructor(builder: FormBuilder) {
// *** this is the important bit - where we define the fields on the form and their validation and default values ***
this.loginForm = builder.group({
userName: ["demo user", Validators.required],
password: ["", Validators.required]
});
}
login(e) {
e.preventDefault();
// TODO - call a service to do the login
// this.loginForm.value.userName gives the username value
// this.loginForm.value.password gives the password value
}
}
Here are some key points …
- [ng-form-model]= on the form tag on line 11 defines the name of our form model. We can reference this in order to extract values from the form - see the comments on lines 37 and 38.
- ng-control= on the input tags defines the name of the fields in our form model. These names match the field names passed into the form builder on lines 30 and 31 and also how you could extract form values on lines 37 and 38
- FormBuilder is passed into the constructor on line 27 and then associated with the form model on line 29. Lines 30 and 31 define the fields in the model - the first element in the array is the default value and the second element is the validation rule
This example is hardly a large complex form but it demonstrates the concepts. What do you think of model driven forms?
If you to learn more about TypeScript, you may find my free TypeScript course useful: