Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 26

UNIT 5-FORMS AND ROUTING IN ANGULAR 4.

Template-driven Forms in Angular

Angular's template-driven forms, one of two form-building methods, simplify


complex form management using Angular's two-way data binding. Unlike
model-driven forms, they rely on HTML directives for form control, making
them asynchronous and view-driven. Ideal for enterprise applications, they
efficiently handle complex, multi-step forms with intricate validation, reducing
the time and potential errors of manual form creation. This article delves into
using template-driven forms for practical scenarios like hospital or school
admissions, emphasizing the need for importing FormModule in Angular's
AppModule.
In Real life example, when you visit hospital a paper present to you and
requested to write basic info about your self. as well as in school admission form
also an example. These information uploaded to software. so form is basically a
paper that collect information. In technical prospective, angular provide us
template driven form to collect information about the things.
Form Setup

We make a basic form component with a basic form template and a simple
component, just like the user profile form component we started with in this
section:

Create a project

First, create a new project named angular-forms by using the following


command:

1. ng new angular-forms

Now, go to the project folder by using the following command.

1. cd angular-forms

Now, use the Angular CLI command ng generate class Hero to generate a new
class named Hero:

1. ng generate class Hero


Go to your project folder angular-forms and open the hero.ts file under the app
module. Write the following code:

1. export class Hero {


2. constructor(
3. public id: number,
4. public name: string,
5. public power: string,
6. public alterEgo?: string
7. ) { }
8. }
The TypeScript compiler generates a public field for each public constructor
parameter and when you create new heroes, it automatically assign the
parameter's value to that field.

Here, alterEgo is optional and the constructor can omit it.

Create a Form component

An Angular form consists of two parts:

o HTML based template


o A component class to handle data and users

Now, generate a new component named HeroForm by using the following


command:

1.ng generate component HeroForm


Revise app.module.ts file

The app.module.ts file is used to define the application's root module. The
template-driven forms reside in their own module. You need to add the
FormsModule to the array of imports for the application module before using
forms.

1. import { NgModule } from '@angular/core';


2. import { BrowserModule } from '@angular/platform-browser';
3. import { FormsModule } from '@angular/forms';
4. import { AppComponent } from './app.component';
5. import { HeroFormComponent } from './hero-form/hero-
form.component';
6. @NgModule({
7. imports: [
8. BrowserModule,
9. FormsModule
10. ],
11. declarations: [
12. AppComponent,
13. HeroFormComponent
14. ],
15. providers: [],
16. bootstrap: [ AppComponent ]
17.})
18.export class AppModule { }
Here, we have imported FormsModule and added the FormsModule to the list
of imports defined in the @NgModule decorator. This is used to access the
application to all of the template-driven forms features, including ngModel.

Revise app.component.html file

The app.component.html is used to host the new HeroFormComponent. It is the


application's root component. Write the following code in app.component.html

1. <app-hero-form></app-hero-form>
Create an initial HTML form template

Use the following code in hero-form.component.html

1. <div class="container">
2. <h1>Hero Form</h1>
3. <form>
4. <div class="form-group">
5. <label for="name">Name</label>
6. <input type="text" class="form-control" id="name" required>
7. </div>
8. <div class="form-group">
9. <label for="alterEgo">Alter Ego</label>
10. <input type="text" class="form-control" id="alterEgo">
11. </div>
12. <button type="submit" class="btn btn-success">Submit</button>
13. </form>
14.</div>
Style the form

Open style.css and use the following code to import the bootstrap file.

1. @import url('https://unpkg.com/bootstrap@3.3.7/dist/css/
bootstrap.min.css');
Add power list by using *ngFor

The hero form can choose power lists from a fixed list of agency-approved
powers. Use the following HTML code immediately below the Alter Ego group
in hero-form.component.html

1. <div class="form-group">
2. <label for="power">Hero Power</label>
3. <select class="form-control" id="power" required>
4. <option *ngFor="let pow of powers" [value]="pow">{{pow}}</
option>
5. </select>
6. </div>

The basic template-driven form is completed now. You can use the ng serve
command to run the project.

OUTPUT:

Directives

The directives we need to construct template-driven forms in angular are in the


FormsModule, so import it and add it as an import to our NgModule.

One of the directives retrieved from the FormsModule is known as NgForm.


This directive's selector matches the <form> tag.

This ngForm object is hidden, but we can disclose it by attaching a local


template reference variable to the form element, as shown:
We can now use the variable userForm in our template to point to
our ngForm directive object.

Two-Way Data Binding

The form module in Angular implements a directive with


the [(ngModel)] selector, which allows us to quickly perform data binding in
two directions: from the view to the model and from the model to the view.

Terminology

[(...)] - Used for two-way binding Also known as banana-in-the-box as it looks


like the same.

Let's take a look at the following simple component:

Here, we've connected [(ngModel)] with the name, so whatever changes we will
do it will be stored in the name variable.

We already know that the (eventName) syntax is used to connect to events


generated by a certain component.

On the other side, we use the [propertyName]= "foo" syntax to create one-way
data binding by setting the value of the property.

The [(ngModel)] syntax combines both to provide bidirectional data binding.

Domain Model

In Angular, we normally won't data bind to a simple string or object on our


component but to a domain model specified via a class or interface, such as
User for our User Profile form.

Now, create an object for the interface User:

Now let's bind all our input controls to our userObj directly, like so:

Form Errors

In template-driven forms, we may handle two types of errors:

1. Handle form submission with ngSubmit and error handling in the submit
function.
2. Add a feature that disables the submit button at first and enables it only
after the form has been validated.
Sub-Form Components

The FormGroup is a FormControl collection. It may also include additional


FormGroups.

When we use the <form>, the ngForm directive constructs the top Level
FormGroup behind the scenes.

Using the ngModelGroup directive, we can create a new FormGroup. Let us add
the street, city, and Pincode form control to the address FormGroup.

Simply wrap the fields within a div element with the ngModelGroup directive
applied to it, as seen below:

Launch the app and submit it. The resulting item is seen below.

Validation

The validators in the model-driven method were defined via code in the
component.

In the template-driven technique, validators are defined in our template through


directives and HTML5 properties. Let's add validators to our form template.

Except for the language, all of the fields were necessary, so we'll just add the
required attribute to those input fields.

Validation Styling

To provide visuals on the screen, we employ several Form Control States such
as valid, touched, and dirty. These are the FormControl properties.

However, with template-driven forms in angular, no FormControl object is


created within the component. So, to access FormControl, we may use one of
the methods listed below.

1. Using .form property of ngForm

Using userForm.form.controls.firstName, we can get the title FormControl


of userForm. We may retrieve the control status of the FormControl using this
object, as illustrated below.

2. Using local template reference variable.


To access control state properties of title control, we need to go
through myForm.form.controls.title.valid. Using the ngModel directive, we can
make this shorter.

As shown below, we are creating a local reference to the title FormControl


using the ngModel directive

Now, we can access the control state of the title using just firstName.valid, as
shown below.

Both ways will give the same output.

Validation Messages

In terms of form validation messages, we may utilize them the same way as in
model-driven forms. We may use the same HTML in our template-driven forms
as long as we name the local reference variables the same as the form controls
in the model-driven method, as seen below:

Submitting the Form

We may submit the form using the ngSubmit directive or on the Submit button's
click event. Either option is acceptable.

Let's add ngSubmit to the form:

user-profile.component.html

Now, we will create one method inside the component.

user-profile.component.ts

Resetting the Form

As with the template-driven form, we may reset the form. As seen below,

Conclusion

 Angular template-driven forms are the easiest way to create interactive


form
 Will have to import FormsModule and add it to
the @NgModule imports array
 Attaching the ngForm directive to the <form> tag will attach a form to
FormsModule, and now it'll have all the properties
 Creating dynamic forms is possible
 Handling errors, domain models and reset forms becomes easy when
using angular forms

Angular Model-Driven (Reactive) Forms:

Angular Model-Driven (Reactive) Forms are an effective tool for managing


form state & validation in Angular applications by synchronizing form controls
with model data. These forms take advantage of the capabilities of RxJS
observables to provide dynamic updates, strong validation, and seamless
integration with component functionality, hence improving the user experience
and developer efficiency.

Angular reactive forms follow a model-driven approach to handle form input


whose values can be changed over time. These are also known as model-driven
forms. In reactive forms, you can create and update a simple form control, use
multiple controls in a group, validate form values, and implement more
advanced forms.

Reactive forms use an explicit and immutable approach to manage the state of
the form at a given point of time. When we change the form state, it returns a
new state which manages the integrity of the models between changes. In
reactive forms, you build your own representation of a form in the component
class.

Reactive forms are easy to test because they assure consistent and predictable
data when requested.

How to add a single form control

In this section, we will describe how to add a single form control. Here, the
users have to enter their name into an input field, form captures that input value,
and displays the current value of the form control element.

Follow these steps:

1. Register the reactive forms module

You have to import ReactiveFormsModule from the @angular/forms package


and add it to your NgModule's imports array to use reactive forms.
1. import { ReactiveFormsModule } from '@angular/forms';
2. @NgModule({
3. imports: [
4. // other imports ...
5. ReactiveFormsModule
6. ],
7. })
8. export class AppModule { }

2. Generate and Import a new form control

First, generate a component for the control by using the following syntax:

1. ng generate component NameEditor

To register a single form control, you have to import the FormControl class into
your component and create a new instance of the form control to save as a class
property. The FormControl class is the basic building block used in reactive
forms.

Write the following code in name-editor.component.ts file:

1. import { Component } from '@angular/core';


2. import { FormControl } from '@angular/forms';
3. @Component({
4. selector: 'app-name-editor',
5. templateUrl: './name-editor.component.html',
6. styleUrls: ['./name-editor.component.css']
7. })
8. export class NameEditorComponent {
9. name = new FormControl('');
10.}

3. Now, register the control in the template

After creating the control in the component class, you have to add it to the form
control element in the template. Use the formControl binding provided by
FormControlDirective to update the template with the form control.

1. <label>
2. Name:
3. <input type="text" [formControl]="name">
4. </label>

We have registered the form control to the name input element in the template.
Now, the form control and DOM element communicate with each other and the
view reflects changes in the model, and the model reflects changes in the view.

4. Display the component

Add the form control component to the template to display the form. Add the
following code to app.component.html.

1. <app-name-editor></app-name-editor>

CUSTOM VALIDATORS

Angular is a powerful front-end framework that allows developers to build


dynamic and interactive web applications. One of the key features of Angular is
its form handling capabilities. Angular provides a set of built-in validators to
perform common form validations such as required fields, email format, and
min/max length. However, there are cases where you need to implement custom
validation logic to meet your application’s specific requirements. In this article,
we will explore how to create custom validators in Angular with examples.

Why Custom Validators?

Custom validators in Angular are essential when you encounter validation


scenarios that cannot be achieved using the built-in validators. Some common
use cases for custom validators include:

1. Password Confirmation: You might want to ensure that two


password input fields match each other.

2. Unique Username: Checking if a chosen username is unique in your


application’s database.

3. Conditional Validation: Implementing complex validation rules


based on the state of other form controls.

Creating a Custom Validator

To create a custom validator in Angular, you need to define a function that


performs the validation logic and returns a validation error object if the
validation fails. This function should adhere to the signature
of ValidatorFn or AsyncValidatorFn based on whether your validation logic is
synchronous or asynchronous.

Synchronous Custom Validator

Here’s an example of a synchronous custom validator that checks if a name


contains only letters:
In this example, we define a letterValidatorfunction that returns a validator
function. The validator function takes a form control as an argument and checks
if it contains only letters. If not, it returns a validation error object with
a invalidSymbols property.

Usage:

Now if form control has invalid symbols we will see error message

And theinvalidSymbols property comes from LetterValidator

Usage of Custom Validator

Interaction with other form controls

Now, let’s assume our validator depends on the value of another form control. A
good example is the password confirmation input

So we need to create a custom validation to confirm that two password fields


match each other. First, let’s create the custom validator function for password
confirmation:
In this code, we define a passwordConfirmationValidator function that takes two
control names as arguments: controlName for the password field
and matchingControlName for the confirmation password field. This function
returns a validator function that compares the values of these two fields and sets
a passwordMismatch error if they do not match.

Now, let’s use this custom validator in an Angular component:

In this component, we import and use


the passwordConfirmationValidator function to create a custom validation rule
for the password confirmation. We apply this custom validator to the form group
by passing the control names ('password' and 'confirmPassword') to
the passwordConfirmationValidator function within the validator option.

Lastly, you can display an error message in your template when the passwords
don’t match:

In the template, we use the *ngIf directive to display an error message when the
'confirmPassword' field has the 'passwordMismatch' error set, indicating that the
passwords do not match.

With this custom validation in place, your Angular registration form will ensure
that the user enters the same password in both the ‘password’ and
‘confirmPassword’ fields
Asynchronous Custom Validator

In this example we will check checking if a chosen username is unique in our


application’s database.

For asynchronous validation, you can use the AsyncValidatorFn. Here's an


example of an asynchronous custom validator that checks if a username is
already taken:

In this example, we define an uniqueUsernameValidator function that returns an


asynchronous validator function. This validator function checks if the username
already exists by calling a userService method. It returns an observable that
emits a validation error object if the username is taken or null if it's available.

Html

<mat-form-field>
<mat-label>User name</mat-label>
<input matInput type="text" placeholder="Name" formControlName="name" />
<mat-error *ngIf="userForm.controls['name'].hasError('usernameTaken')">
Username is taken
</mat-error>
</mat-form-field>

Example

Async validator example

Note: When the request is pending, userForm.invalid becomes false

Conclusion

Custom validators are a powerful tool in Angular for handling complex form
validation requirements. By creating custom validators, you can tailor your
validation logic to the specific needs of your application. Whether you need to
perform synchronous or asynchronous validation, Angular provides a flexible
framework to implement and use custom validators effectively. So, don’t
hesitate to leverage custom validators to enhance the user experience in your
Angular applications.

Dependency Injection in Spring

AngularJS comes with a built-in dependency injection mechanism. It facilitates


you to divide your application into multiple different types of components
which can be injected into each other as dependencies.

Dependency Injection is a software design pattern that specifies how


components get holds of their dependencies. In this pattern, components are
given their dependencies instead of coding them within the component.

Modularizing your application makes it easier to reuse, configure and test the
components in your application. Following are the core types of objects and
components:

o value
o factory
o service
o provider
o constant

These objects and components can be injected into each other using AngularJS
Dependency Injection.

Value

In AngularJS, value is a simple object. It can be a number, string or JavaScript


object. It is used to pass values in factories, services or controllers during run
and config phase.

1. //define a module
2. var myModule = angular.module("myModule", []);
3. //create a value object and pass it a data.
4. myModule.value("numberValue", 100);
5. myModule.value("stringValue", "abc");
6. myModule.value("objectValue", { val1 : 123, val2 : "abc"} );
Here, values are defined using the value() function on the module. The first
parameter specifies the name of the value, and the second parameter is the value
itself. Factories, services and controllers can now reference these values by their
name.

Injecting a value

To inject a value into AngularJS controller function, add a parameter with the
same when the value is defined.

1. var myModule = angular.module("myModule", []);


2. myModule.value("numberValue", 100);
3. myModule.controller("MyController", function($scope, numberValue) {
4. console.log(numberValue);
5. });

Factory

Factory is a function that is used to return value. When a service or controller


needs a value injected from the factory, it creates the value on demand. It
normally uses a factory function to calculate and return the value.

Let's take an example that defines a factory on a module, and a controller which
gets the factory created value injected:

1. var myModule = angular.module("myModule", []);


2. myModule.factory("myFactory", function() {
3. return "a value";
4. });
5. myModule.controller("MyController", function($scope, myFactory) {
6. console.log(myFactory);
7. });
Injecting values into factory

To inject a value into AngularJS controller function, add a parameter with the
same when the value is defined.

1. var myModule = angular.module("myModule", []);


2. myModule.value("numberValue", 100);
3. myModule.controller("MyController", function($scope, numberValue) {
4. console.log(numberValue);
5. });
Note: It is not the factory function that is injected, but the value produced by
the factory function.

Service

In AngularJS, service is a JavaScript object which contains a set of functions to


perform certain tasks. Services are created by using service() function on a
module and then injected into controllers.

1. //define a module
2. var mainApp = angular.module("mainApp", []);
3. ...
4. //create a service which defines a method square to return square of a nu
mber.
5. mainApp.service('CalcService', function(MathService){
6. this.square = function(a) {
7. return MathService.multiply(a,a);
8. }
9. });
10.//inject the service "CalcService" into the controller
11.mainApp.controller('CalcController', function($scope, CalcService, defau
ltInput) {
12. $scope.number = defaultInput;
13. $scope.result = CalcService.square($scope.number);
14. $scope.square = function() {
15. $scope.result = CalcService.square($scope.number);
16. }
17.});

Provider

In AngularJS, provider is used internally to create services, factory etc. during


config phase (phase during which AngularJS bootstraps itself). It is the most
flexible form of factory you can create. Provider is a special factory method
with a get() function which is used to return the value/service/factory.

1. //define a module
2. var mainApp = angular.module("mainApp", []);
3. ...
4. //create a service using provider which defines a method square to return
square of a number.
5. mainApp.config(function($provide) {
6. $provide.provider('MathService', function() {
7. this.$get = function() {
8. var factory = {};
9. factory.multiply = function(a, b) {
10. return a * b;
11. }
12. return factory;
13. };
14. });
15.});

Constants

You cannot inject values into the module.config() function. Instead constants
are used to pass values at config phase.

1. mainApp.constant("configParam", "constant value");

Let's take an example to deploy all above mentioned directives.

1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>AngularJS Dependency Injection</title>
5. </head>
6. <body>
7. <h2>AngularJS Sample Application</h2>
8.
9. <div ng-app = "mainApp" ng-controller = "CalcController">
10. <p>Enter a number: <input type = "number" ng-model = "number"
/></p>
11. <button ng-click = "square()">X<sup>2</sup></button>
12. <p>Result: {{result}}</p>
13. </div>
14.
15. <script src = "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/
angular.min.js"></script>
16.
17. <script>
18. var mainApp = angular.module("mainApp", []);
19.
20. mainApp.config(function($provide) {
21. $provide.provider('MathService', function() {
22. this.$get = function() {
23. var factory = {};
24.
25. factory.multiply = function(a, b) {
26. return a * b;
27. }
28. return factory;
29. };
30. });
31. });
32.
33. mainApp.value("defaultInput", 10);
34.
35. mainApp.factory('MathService', function() {
36. var factory = {};
37.
38. factory.multiply = function(a, b) {
39. return a * b;
40. }
41. return factory;
42. });
43.
44. mainApp.service('CalcService', function(MathService){
45. this.square = function(a) {
46. return MathService.multiply(a,a);
47. }
48. });
49.
50. mainApp.controller('CalcController', function($scope, CalcService,
defaultInput) {
51. $scope.number = defaultInput;
52. $scope.result = CalcService.square($scope.number);
53.
54. $scope.square = function() {
55. $scope.result = CalcService.square($scope.number);
56. }
57. });
58. </script>
59. </body>
60.</html>

Dependency injection (DI) is a programming method that separates component


creation and usage. The design pattern appears in object-oriented
programming and adheres to the SOLID principles (specifically the S and
the D). Similar ideas also apply to other programming paradigms, such
as procedural or functional programming.

The term consists of two keywords, which help demystify the concept:

 Dependencies. Code components rely on many objects and services


(dependencies) to carry out their tasks. Different dependencies exist, such
as outside resources, other objects, or services.
 Injection. Components do not make or link dependencies internally in
DI. Instead, the technique provides (injects) dependencies from the
outside. This approach creates a separation between components and
dependencies.

Dependencies come in various shapes and forms. They are essential for a
component to work but are not part of the component itself. APIs,
libraries, databases, and other components can all act as dependencies.

Dependency injection solves the dependency management challenge. By


separating dependency management from a component, an external source
creates and manages the dependencies.

Separation (or decoupling) reduces the number of connections between


components and modules. Fewer connections result in simplified maintenance
and flexibility. As a result, code becomes reusable because components are
independent and applicable to various contexts. Teams do not require constant
coordination and can develop modules in parallel.

Why Use Dependency Injection?

There are several key reasons to use dependency injection. Some of the main
benefits include:

 Readability. DI promotes division between a component's logic and its


dependencies. Code is easier to read and better organized.
 Reusability. Components with injected dependencies are easy to reuse
for different projects due to being independent. DI provides a templating
approach to coding, reducing repeated code blocks and rewriting across
different projects.
 Testability. Dependency injection simplifies writing unit tests for
individual components. Regular testing leads to dependable code with
fewer bugs.
 Maintainability. Due to fewer connections between components and
modules, changing or improving individual code parts does not affect
other parts of the code.

Dependency Injection Types

Developers use various techniques to implement dependency injection. Choose


the approach that best suits the requirements, programming language, and use
case. Below is a brief overview and example of some dependency injection
types.

Constructor Injection

Constructor injection is a dependency injection type that injects dependencies


through a constructor. When an instance of a class or object is created, the
constructor provides the dependencies during creation. As a result, the class or
object runs correctly and immediately has all the necessary dependencies.

Use constructor injection when the dependencies are required for a class or
object to function. The dependencies are injected during class or object
instantiation and make dependencies immediately available to a class or object
instance.

Setter Injection

Setter injection is a dependency injection that provides dependencies through


setter methods or class properties. A developer updates the dependencies
manually after object or class instantiation. As a result, the object receives
appropriate dependencies when the setter methods are called.

Use setter injection when a class or object functions without mandatory


dependencies. In this case, the dependencies are optional during instantiation
and can be injected after runtime. This approach allows modifying
dependencies dynamically after object creation.

Method Injection

Method injection (or parameter injection) is a dependency injection type that


provides dependencies as method parameters. The class or object expects
dependencies as arguments when calling a method.

Use method injection for fine-grained dependency injection based on individual


methods. Method injection achieves the highest decoupling degree and is useful
when a class has multiple methods that do not require the same dependencies.

How Does Dependency Injection Work?

The dependency injection process uses four main components (roles):

1. Service. A component that provides a function or service. Other components


depend on the provided service.

2. Client. A component or class that depends on the service to perform tasks.


The client does not create or manage the service; it relies on a DI process to
provide the service.

3. Injector. Creates and manages service instances and injects them into clients.
The injector resolves all dependencies and connects components as required.

4. Interface. The interface (or contract) defines methods or properties a service


implements. The abstraction is an agreement between the service and the client,
ensuring the service addresses all rules and expectations.
The dependency injection process goes through the following steps:

 Defining dependencies. Determine resources that classes and


components need to function.
 Defining interfaces (contracts). Create an interface for each
dependency. Provide the methods or properties that serve as contract
rules.
 Injecting dependencies. Choose a mechanism to inject dependencies
into classes or components. Depending on the mechanism, this step
happens manually, with a DI container or a framework.
 Using dependencies. Classes and components use the dependencies by
interacting with the defined contracts.

Dependency Injection Advantages and Disadvantages

There are both advantages and disadvantages when implementing dependency


injection. Although the approach improves code maintainability, there's a steep
learning curve and added code complexity.

Below is a brief overview of DI's main advantages and disadvantages.

Advantages

The main advantages of dependency injection are:

 Logical separation. Loose coupling between components and


dependencies makes code easier to read and maintain. Classes and objects
do not handle dependency instantiation or management.
 Improved testing. DI simplifies unit testing. Creating mock
dependencies or testing individual components is simplified.
 Flexible dependency management. Separating dependencies and
components provides flexibility. Different dependencies can be injected,
which creates an easily adaptable environment.
 Reusable components. Due to loose coupling between components and
dependencies, the code is reusable in different contexts and
environments.
 Simpler maintenance. Upgrading libraries or components does not affect
the underlying dependent class.
 Concurrent development. Developers can work on modules and
dependencies in parallel while adhering to the defined contracts.

Disadvantages

The disadvantages of dependency injection are:

 Complexity. When handling many dependencies or complex


configurations, DI additionally increases code complexity.
 Learning curve. The concepts behind DI and when to apply them take
time to grasp fully. Initial project development slows down due to the
learning curve.
 Overhead. DI is not suitable for smaller projects, as it adds redundant
overhead.
 Runtime errors. Dependencies that are not carefully injected result in
runtime errors. Troubleshooting is challenging, especially in complex
environments.

You might also like