Angular Forms: Reactive Forms and Template- Driven Forms
Angular Forms
Forms are an integral part of a web application. Practically every application comes with forms to be filled in by the users. Angular forms are used to log in, update a profile, enter sensitive information, and perform many other data entry tasks.
Ø Types of Angular Forms:
There are two types of form building supported by Angular Forms;
1. Template- Driven Forms:
ü In this method, the conventional form tag is used to crate forms. Angular automatically interprets and creates a form object representation for the tag.
ü Controls can be added to the form using the NgModel tag. Multiple controls can be grouped using the NgControlGroup module.
ü A form value can be generated using the form.value object. Form data is exported as JSON values when the submit method is called.
ü Basic HTML validations can be used to validate the form fields. In case of custom validations, directives can be used.
ü Arguably, this method is simplest way to create an Angular App.
2. Reactive Forms:
ü This approach is the programming paradigm oriented around data flows and propagation of change.
ü With Reactive Forms, the component directly manages the data flows between the form controls and the data models.
ü Reactive forms are code-driven, unlike the template-driven approach.
ü Reactive forms break from the traditional declarative approach.
ü Reactive forms eliminate the anti-pattern of updating the data model via two-way data binding.
ü Typically, Reactive form control creation is synchronous and can be unit tested with synchronous programming techniques.
Ø Form Controls:
Form Control is a class that enables validation. For each input field, an instance of this class is created. These instances help check the values of the field and see if they are touched, untouched, dirty, valid, invalid, and so on. Every form input user has in a reactive form should be bound by a form control. These are the basic units that make up reactive forms.
Ø Form Groups:
FormGroup class represents a group of controls. A form can have multiple control groups. The Form Group class returns true if all the controls are valid and also provides validation errors, if any. Every single form control in the form group is identified by name when initializing.
ü Steps to add a FormControl to a FormGroup:
1. addControl()- Adds a control and updates its value and validity
2. removeControl()- Removes a control
3. setControl()- Replaces an existing control
4. contains()- Checks for enabled controls associated with a given name
5. registerControl()- Registers a control but, unlike the other methods, does not update its value and validity
Ø FormArray:
It is used to track the same values and status for an array of form controls.
Ø ControlValueAccessor:
Create a bridge between Angular FormControl instances and built in DOM elements.
v FormBuilder:
Setting up form controls can be very tedious job, especially if user are working with very long forms. Angular’s FormBuilder helps user streamline the process of building advanced forms while avoiding repetition.
v Data Flow in Angular Forms:
1. Data Flow in Reactive Forms:
In Reactive form, each form element in the view is directly linked to a form model (FormControl instance). Any updating from the view to the model and the model to the view are synchronous and are not dependent on the User Interface.
Data Flow from View to Model
Steps in data flow from
view to model in Reactive forms:
ü First, the user types a value into the input element. In this example, the input element is favorite Color and the typed value is Blue.
ü Then, the form input elements emits an input event with the latest typed value.
ü Then the control value accessor (means who listen for events on the form input element) immediately relays the new value to the FormControl instance.
ü After receiving the value the FormControl instance emits the new value through the valueChanges observable.
ü Now, Finally user will receive the new value as an output.
Data Flow from Model to View
Steps in data flow from
Model to view in Reactive forms:
ü First, the user calls the favoriteColorControl.setValue() method. This method updates the FormControl value.
ü Then, the FormControl instance emits the new value through the valueChanges observable.
ü Then, finally end user receives the new value.
ü At last, the control value accessor on the form input element updated the element with the new value.
2. Data Flow in Template-Driven Forms:
Every form element of the template driven forms is linked to a directive to manage the form model internally.
Data flow from View to Model
Steps: Here the user has to change the input value from red to blue
ü First, the user types Blue into the input element
ü Then, theinput element emits an input event having the value Blue.
ü Then, the control value accessor attached to the input triggers the setValue() method on the FormControl instance.
ü After the setValue(), the FormControl instance emits the new value through the
valueChanges observable.
ü Now, the end user will receive the new value.
ü After that, the control value accessor also calls the NgModel.viewToModelUpdate() method which emits an ngModelChange event.
ü Here, component template uses two-way data binding for the favoriteColor property, the favoriteColor property in the component is updated to the value emitted by the ngModelChange event (Blue).
v Directives:
Directives are used to manipulate the DOM. By using Angular directives, user can change the appearance, behavior or a layout of a DOM element, It also helps user to extends HTML.
Angular directives can be classified in 3 categories based on how they behave;
1. Component Directives:
This directives are used in main class. They contain the detail of how the component should be processed, instantiated and used at runtime.
2. Structural Directives:
These directives start with a * sign and are used to manipulate and also change the structure of the DOM element. For example, *ngIf directive, *ngSwitch directive, and *ngFor directive.
1. *ngIf Directive: -This directive allows users to add/remove DOM element.
2. *ngSwitch Directive: This directive allows users to add/remove DOM element. This is very similar to switch statement in C#.
3. *ngFor Directive: This directive is used to repeat a portion of HTML template once per each item from an iterable list/ collection.
3. Attribute Directives:
This directives are used to change the loop and behavior of the DOM elements. For Ex. ngClass and ngStyle directives.
1. ngClass Directive: This directive is used to add or remove CSS classes to an HTML element.
2. ngStyle Directive: This directive facilitates user to modify the style of an HTML element using the expression. User can also use ngStyle directive to dynamically change the style of user HTML element.
v Condition with Ngif:
Built-in directives are attributes which we add to HTML element to give dynamic behavior. Angular provides various built-in directives.
ü The ngif directives is used to add or remove HTML elements according to the expression.
ü This expression must return a Boolean value.
ü If the expression is true, then the element is inserted, otherwise element is removed.
ü Placing the ngIf directive on a component, or an element, will in fact hide or show that element based on the expression user pass it to be evaluated.
Syntax: <p *ngIf=“condition”>
True statements
</p>
<p *ngIf=“!condition”>
False statements
</p>
E.g:
<div
*ngIf=”isLoggedIn”>
<!– If user is logged in –>
<label class=”Angular_Example”>Hello, User!</label>
<button class=”btn-primary” (click)=”isLoggedIn = !isLoggedIn”>
Logout
</button>
</div>
<div *ngIf=”!isLoggedIn”>
<!– If user is NOT logged in –>
<button class=”Angular_example2″
(click)=”isLoggedIn = !isLoggedIn”>
Login
</button>
<button class=”btn-primary”>Signup</button>
</div>
E.g-2 // if with else
<div
*ngIf=”isLoggedIn; else loggedOut”> <!– If NOT logged in use #loggedOut
template–>
<label class=”Angular_Example”>Hello, User!</label>
<button class=”btn-primary” (click)=”isLoggedIn = !isLoggedIn”>
Logout
</button>
</div>
<ng-template #loggedOut>
<!– loggedOut template –>
<div>
<button class=”btn-default mr-2″(click)=”isLoggedIn = !isLoggedIn”>
Login
</button>
<button class=”btnbtn-primary”>Signup</button>
</div>
</ng-template>
E.g:-3. If then else condition
<div *ngIf=”isLoggedIn; then loggedIn; else loggedOut”></div>
<!–If logged in, then use loggedIn template, else use loggedOut template –>
<ng-template #loggedIn> <!– loggedIntemplate–>
<div>
<label class=”mr-2″>Hello, User!</label>
<button class=”btn-primary” (click)=”isLoggedIn = !isLoggedIn”>
Logout
</button>
</div>
</ng-template>
<ng-template #loggedOut> <!– logged Out template –>
<div>
<button class=”btnbtn-default mr-2″ (click)=”isLoggedIn = !isLoggedIn”>
Login
</button>
<button class=”btnbtn-primary”>Signup</button>
</div>
</ng-template>
v NgSwitch:
ü A switch is usually more efficient than a set of nested ifs.
ü ngSwitch directive is used to bind element with DOM based on a matching condition.
ü ngSwitchCase directive is used to describes the known results.
ü ngSwitchDefault is used to handle all the other unknown cases.
ü Every view that matches is rendered.
ü If there are no matches, a view with the ngSwitchDefault directive is rendered.
ü If there are no matches, and there is no ngSwitchDefault than nothing is rendered.
E.g: <div class=“container” [ngSwitch]=“myVar”>
<div *ngSwitchCase=“‘A'”>Var is A</div>
<div *ngSwitchCase=“‘B'”>Var is B</div>
<div *ngSwitchCase=“‘C'”>Var is C</div>
<div *ngSwitchDefault>Var is something else</div>
</div>
v ngFor Directive:
The *ngFor directive is used to repeat a portion of HTML template once per each item from an iteration list / collection. The ngFor is an Angular structural directive and is similar to ngRepat in AngularJS. Some local variables like Index, First, Last, Odd and even are exported by *ngFor directive.
Syntax: *ngFor=”let <value> or <collection>”
Here, <Value> is a variable name decided by user, <collection> is a properly on your
component which holds a collection, usually an array but anything that can be iterated over in a for-of loop.
E.g:@Component({
selector: ‘ngfor-example’,
template: `
<ul>
<li *ngFor=”let person of
people”> (1)
{{ person.name }}
</li> </ul>
`})
class NgForExampleComponent {
people: any[] = [
{ “name”: “Aashutosh” },
{ “name”: “Mahesh” },
{ “name”: “Chandresh” },
{ “name”: “Rudra” },
{ “name”: “Shivansh” }
];
}
1. Index: Sometimes user also want to get the index of the item in the array, user can do this by adding another variable into ngFor expression and making it equal to index.
<ul> (1)
<li *ngFor="let person of people; let i = index">
(1)
{{ i + 1 }} - {{ person.name }} (2)
</li>
</ul>
ü Declare variable i and make it equal to the special keyword index.
ü We can use the variable I just like the variable person in above example.
ü The index is always zero based, so starts at 0,1,2,3…n
2. Even and Odd:
Another very common functionality needed when user building a table by adding a different css class to the even or odd rows. User can add a CSS class even if the row is even and the CSS class off if the row is odd. In order to so, we have a couple of variables available for that like even and odd with ngClass:
</tr *ngFor=”person of people; let even=even;let odd=odd”
[ngClass]=”{ odd: odd, even: even }“> |
<td>{{person.name}}</td> |
</tr> |
3. First and Last:
Just like the even and odd functionality, there are also two other variables that can be used to identify the first and last elements of the list:
</tr *ngFor=”person of people; let first = first;let last =
last”
[ngClass]=”{ first: first, last: last }“> |
<td>{{person.name}}</td> |
</tr> |
Ø How ngFor tracked various list items?
ngFor by default tracks list items using object identity. This means that if user build a list of new objects from scratch with the exact same values as the previous list and pass this newly built list to ngFor, Angular will not be able to tell that a given list item is already present or not.
v Passing Data into a Component:
There are two ways to pass data into a component, with ‘property binding’ and ‘event binding’. In Angular, data and event change detection happens top-down from parent to child. However for angular events we can use the DOM event mental model where events flow bottom-up from child to parent. So, Angular events can be treated like regular HTML DOM based events when it comes to cancellable event propagation.
The @input() decorator defines a set of parameters that can be passed down from the component’s parent. The point of making components is not only encapsulation, but also reusability. Inputs allows us to configure a particular instance of a component.
v ngOnInit:
ngOnInit is a lifecycle hook in Angular that is called after the constructor is called and after the component’s inputs have been initialized. It is used to perform any additional initialization that is required for the component. ngOnInit is commonly used to call services or to set up subscriptions.
v Styling with components:
Angular applications are styled with standard CSS. That means user can apply everything user know about CSS stylesheets, selectors, rules and media queries directly to angular applications. Additionally, Angular can bundle component styles with components, enabling a more modular design than regular stylesheets. For every Angular component user can write, and not only define an HTML template, but also the CSS styles that go with that template, specifying any selectors, rules and media queries that user need. One way to do this is to set the styles property in the component metadata. The styles property takes an array of strings that contain CSS code. Every app framework offers different ways of styling HTML components. In Angular, there are two ways to keep CSS
code to style your component’s HTML template.
1. Keep the CSS inline
2. Keep the CSS separately in its own file
For each of these methods, a different property in component’s metadata has to be used. Styles property should be used when the number of style properties is less than ten or so. If you have to define a lot of CSS styles, then it is always better to put them in separate files and use the styleUrls property to point to them.