With the release of Angular 2 just around the corner and also Alfresco’s announcement of enhanced support for Angular 2, we thought it would be a great idea to start a blog series on Angular2 and share our experience with Angular 2 since we recently implemented an angular application which gathers data, connect to Alfresco and populated it as metadata in Alfresco. So we are going to have a two part blog series on firstly Building a Form in Angular 2 and secondly connecting to Alfresco.
Angular 2 Forms
Angular 2 provides two ways of building forms namely Template driven forms and Model driven forms. We have used Template driven form for our application, so this blog is mainly going to be focused on Template based forms.
Template Driven Form
An Angular form has two parts: an HTML-based template and a code-based Component to handle data and user interactions.
Form Component
As is customary with any angular application, we start off by defining a component which would state what exactly we want to do in the form. So we created our component file called media-form-component.ts and included the NgForm directive to be able to exploit their inbuilt controls and validation features. So our form component imports look like the following;
import { Component, OnInit } from '@angular/core'; import { NgForm } from '@angular/common'; import { MediaData } from './media-data'; import { SeedService } from './services/seedService';
Media-data is a model class defined to hold the values when a user enters form data and whose instance gets updated based on the captured changes made on the form. We will discuss more about SeedService in our next blog.
So once we have imported the required directives/classes, we define our component details as follows
@Component({ selector: 'media-form', templateUrl: 'app/media-form.component.html', providers: [ SeedService ] })
- The @Component selector value of “media-form” means we can drop this form in a parent template with a <media-form> tag.
- The templateUrl property points to a separate file for the template HTML called media-form.component.html which would be described later in this blog.
Lastly we export our component class to that it’s available to our angular application as follows;
export class MediaFormComponent {}
Any method that you would like to call from within the form would be implemented in the class MediaFormComponent. We can also inject an instance of our service for example to connect to Alfresco. More details on this in our next blog.
HTML Template
A snippet of our HTML template is shown below;
<form *ngIf="active" (ngSubmit)="onSubmit()" #mediaForm="ngForm"> <div class="form-group"> <div class="fr_text_block"> <div class="fr-text"> <h4>Media Name *</h4> </div> </div> <input type="text" class="form-control fr_input_7" required [(ngModel)]="model.subjectName" ngControl="subjectName" #subjectName="ngForm" /> <div *ngIf ="subjectName.dirty && !subjectName.valid" class="alert alert-danger fr_alert"> <h4>Media Name is required</h4> </div> </div> <div class="fr_grid"> <button type="submit" class="btn fr_button_fill_grey fr_button9" [disabled]="!mediaForm.form.valid" (click) ="scrollTop()"> <div class="fr-text">Submit</div> </button> </div>
</form>
The following describes the pertinent bit of the our HTML template;
- *ngIf
Angular conditional control used to show the form only if the active flag is set to true.
- ngSubmit
Event handler used to trigger the method onSubmit() (defined in our form component class) upon form submission
- ngModel
Used to create a bidirectional binding between the form and the data model
- ngControl
Event handler used to capture the state of the input field
- required
Attribute to mark mandatory fields
Form Validation
Angular is actually tracking three form field states for us and applying the following CSS classes to both the form and its controls:
- touched or untouched
Control has been visited
- valid or invalid
Control’s value is valid
- pristine or dirty
Control’s value has changed
When a user clicks a required field, the field is shown in red until the user types in something. These CSS state classes are very useful for styling form error states.
Note
- As shown above in the form component definition we referenced a “templateUrl” but we could have also used “template” and define the html tags directly in the component as shown below;
template: ‘<h1>Media Form</h1>’
- The container, form-group, form-control, and btn classes come from Twitter Bootstrap and are used only from a look and feel perspective.
Conclusion
The main difference between model driven and template driven forms is that model driven forms allows having custom validators and can also be unit tested compared to Template driven form. We have used Template based form for our solution due to its simplicity and it suited our requirements. We will get into more into the Angular Service, Method calls and connection to Alfresco in our next blog.