Angular
Angular
Angular
Module Overview
In this module, students will be able to learn about frontend technologies such as HTML5, CSS3, Bootstrap, JavaScript
and TypeScript.
Module Objective
The Objectives of this module is to:
What is Angular?
Angular applications are built around a design pattern called ModelView-Controller (MVC).
It all started in 2008 and 2009, Misko hevery (a developer at Google) working on a part time project
to simplify web application development.
Frameworks in general boost web development efficiency and performance by providing a consistent structure so that
developers don’t have to keep rebuilding code from scratch. Frameworks are time-savers that offer developers a host
of extra features that can be added to the software without requiring extra effort.
“Angular” is the catch-all term for the various framework versions out there. Angular was developed in 2009, and as a
result, there have been many iterations.
First, there was the original Angular, called Angular 1 and eventually known as AngularJS. Then came Angulars 2, 3, 4, 5,
until finally, the current version, Angular 11, released on 11/11/2020. Each subsequent Angular version improves on its
predecessor, fixing bugs, addressing issues, and accommodating increasing complexity of current platforms.
If you want to design apps better suited for mobile devices, and/or more complex apps, you had best to upgrade to its
current version.
DOM (Document Object Model) treats an XML or HTML document as a tree structure in which each node represents a
part of the document.
2. TypeScript
TypeScript defines a set of types to JavaScript, which helps users write JavaScript code that is easier to understand. All
of the TypeScript code compiles with JavaScript and can run smoothly on any platform. TypeScript is not compulsory for
developing an Angular application. However, it is highly recommended as it offers better syntactic structure—while
making the codebase easier to understand and maintain.
3. Data Binding
Data binding is a process that enables users to manipulate web page elements through a web browser. It employs
dynamic HTML and does not require complex scripting or programming. Data binding is used in web pages that include
interactive components, such as calculators, tutorials, forums, and games. It also enables a better incremental display
of a web page when pages contain a large amount of data.
Angular uses the two-way binding. The model state reflects any changes made in the corresponding UI elements.
Conversely, the UI state reflects any changes in the model state. This feature enables the framework to connect the
DOM to the model data through the controller.
4. Testing
Features of Angular 7
CLI prompts
In Angular 7, the CLI prompts have been updated to v7.0.2 with new features. For instance, it will now prompt users
when typing commands like @angular/material, ng-new, and ng-add to help them discover the in-built SCSS support,
routing, and more.
The Angular 7 introduced minor visual updates & improvements in Material Design that earlier received a major update
this year only.
The new drag-drop module basically provides a better way to easily create drag & drop interfaces, which is backed by
sorting within a list, support for free dragging, animations, custom drag handles, transferring items between lists,
Virtual scrolling
Like mentioned earlier, the new Virtual Scrolling in Angular 7 basically loads and unloads items from the DOM depending
upon visible parts of lists, resulting into a much faster experiences for users having huge scrollable lists.
The development team at Google have always focused on the performance improvements, and while doing so, they
recently found that most of the developers were using reflect-metadata in their production, which actually was only
Documentation updates
Dependency updates
Documentation are not the only things that have been updated. Even the dependencies have undergone upgradation
Angular Architecture
Angular is a full-fledged model-view-controller (MVC) framework. It provides clear guidance on how the application
should be structured and offers bi-directional data flow while providing real DOM.
1. Modules
An Angular app has a root module, named AppModule, which provides the bootstrap mechanism to launch the
application.
2. Components
Each component in the application defines a class that holds the application logic and data. A component generally
defines a part of the user interface (UI).
3. Templates
The Angular template combines the Angular markup with HTML to modify HTML elements before they are displayed.
There are two types of data binding:
Event binding: Lets your app respond to user input in the target environment by updating your application data.
Property binding: Enables users to interpolate values that are computed from your application data into the HTML.
4. Metadata
Metadata tells Angular how to process a class. It is used to decorate the class so that it can configure the expected
behavior of a class.
When you have data or logic that isn’t associated with the view but has to be shared across components, a service class
is created. The class is always associated with the @Injectible decorator.
6. Dependency Injection
This feature lets you keep your component classes crisp and efficient. It does not fetch data from a server, validate the
user input, or log directly to the console. Instead, it delegates such tasks to the services.
Environment Setup
Let us see how you can install the prerequisites needed to run your first Angular 7 app.
You must have an IDE like Visual Studio Code IDE or JetBrains WebStorm to run your Angular 7 app. VS Code is light and
easy to setup, it has a great range of built-in code editing, formatting, and refactoring features. It is free to use. It also
provides a huge number of extensions that will significantly increase your productivity.
2. Install Node.js
You should install node.js to run your Angular 7 app. It manages npm dependencies support some browsers when
loading particular pages. It provides the required libraries to run Angular project. Node.js serves your run-time
environment as your localhost.
Visit the link and download from the node.js official website: https://nodejs.org/en/download/
To operate on your application after installing Angular CLI, you'll have to run two commands: one to create a project
and the other to support it using a local development server. Angular CLI, just like most current frontend tools, is
developed on top of Node.js.
Some of the things you can use Angular CLI for include;
The next step is to install Angular CLI. Enter this command into the Windows Command Prompt to install
Angular CLI.
Verify the configured version after you've added all of the packages using ng –version.
• The software package manager npm uses command line input to install software:
4. Install npm
This means that you have to install Node.js to get npm installed on your computer.
• The name npm (Node Package Manager) stems from when npm first was created as a package manager for
Node.js.
• All npm packages are defined in files called package.json.
• The content of package.json must be written in JSON.
• At least two fields must be present in the definition file: name and version.
The Angular Framework, Angular CLI, and components used by Angular applications are packaged as npm packages
and distributed using the npm registry.
You can download and install these npm packages by using the npm CLI client, which is installed with and runs as a
Node.js® application. By default, the Angular CLI uses the npm client.
• package.json is a JSON file that lives in the root directory of your project. Your package.json holds important
information about the project.
• It contains human-readable metadata about the project (like the project name and description) as well as
functional metadata like the package version number and a list of dependencies required by the application.
1. Refer to the environment setup of angular given in the above modules. Download all the necessary software and
install it to start with designing an angular application.
2. Make a note of downloading the recent versions of the software.
The process of loading the index.html page, app-level module, and app-level component is called bootstrapping, or
loading the app. In this guide, you will learn about the internals of the bootstrapping process.
• Load index.html
• Load Angular, Other Libraries, and App Code
Load index.html
The starting point of any Angular web application is the index.html page. Index.html is usually the first page to load. Let
us open the file and find out what it contains. You will find it under the src folder.
There are no javascript files in the index.html. Neither you can see a stylesheet file. The body of the files has the following
HTML tag.
Building Application
To run our application, we use the Angular CLI command ng serve or NPM command npm start (npm start command
actually translates into ng serve.)
We use ng build to build our app. Open the command prompt and run the command. This will build and copy the output
files to the dist folder.
You can see that the compiler included five script files. They are runtime, polyfills, styles, vendor, & main. All these files
have two versions one is es5 & the other one es2015.
Application Loads
When index.html is loaded, the Angular core libraries, third-party libraries are loaded. Now the angular needs to locate
the entry point.
The entry point of our application is main.ts. You will find it under the src folder.
angular.json
The Angular finds out the entry point from the configuration file angular.json. This
file is located in the root folder of the project.
What is platformBrowserDynamic
• platformBrowserDynamic is the module, which is responsible for loading the Angular application in the desktop
browser.
• The Angular Applications can be bootstrapped in many ways and in many platforms. For example, we can load
our application in a Desktop Browser or in a mobile device with Ionic or NativeScript.
The above line imports AppModule. The AppModule is the Root Module of the app. The Angular applications are
organized as modules. Every application built in Angular must have at least one module. The module, which is loaded
first when the application is loaded is called a root module.
Root Module
The angular bootstrapper loads our root module AppModule. The AppModule is located under the folder src/app. The
code of our Root module is shown below.
The root module must have at least one root component. The root component is loaded, when the module is loaded by
the Angular.
We use @NgModule class decorator to define an Angular Module and provide metadata about the Modules.
imports
We need to list all the external modules required including other Angular modules, that is used by this Angular Module
Declarations
The Declarations array contains the list of components, directives, & pipes that belong to this Angular Module. We have
only one component in our application AppComponent.
Providers
The Providers array, is where we register the services we create. The Angular Dependency injection framework injects
these services in components, directives. pipes and other services.
Bootstrap
The component that angular should load, when this Angular Module loads. The component must be part of this module.
We want AppComponent load when AppModule loads, hence we list it here.
The Angular reads the bootstrap metadata and loads the AppComponent
Component
The @Component class decorator provides the metadata about the class to the Angular. It has 3 properties in the above
code. selector, templateURL & styleUrls
templateURL
This property contains an HTML template, which is going to be displayed in the browser. The template file is
app.component.html
selector
This property specifies the CSS Selector, where our template will be inserted into the HTML. The CSS Selector in our
code is app-root.
Template
The integral part of Angular component is Template. It is used to generate the HTML content.
The AppComponent defines the template as app.component.html and the CSS Selector is app-root.
The Angular locates app-root in our index.html and renders our template between those tags.
Activity Two
Project Setup
2. Open visual code, click on File, select Open Folder (ctrl+O) then click on it.
4. In Terminal, Type the CLI command ng new and provide the name my-app, as shown here:
5. The ng new command prompts you for information about features to include in the initial app. Accept the
defaults by pressing the Enter or Return key.
The Angular CLI installs the necessary Angular npm packages and other dependencies. This can take a few minutes.
The CLI creates a new workspace and a simple Welcome app, ready to run.
Other files: As a beginner you don’t need these files at this time,
don’t bother about that. These all are used for editor configurations
and information needed at compile time. The builtin webpack in
angular CLI manages all for you.
• index.html This is the entry point for the application, app-root tag is the entry point of the
application on this single page application, on this page angular will add or remove the content
from the DOM or will add new content to the DOM. Base href=”/” is important for routing
purposes.
• app.module.ts: This is the main module file for the project. Each Angular project is divided into
modules to make the project management easy.
• app.component.html This file is used to make changes to the page. You can edit this file as an
HTML file.
• app.component.spec.ts These are automatically generated files which contain unit tests for
source component.
• app.component.ts You can do the processing of the HTML structure in the .ts file. The
processing will include activities such as connecting to the database, interacting with other
components, routing, services, etc.
• app.component.css Here you can add CSS for your component.
Let us create an application where, you can add the name, age, email id, password of the employee to register for the
company.
Step 1: In Terminal, Type the CLI command ng new and provide the name my-app, as shown here:
Step 2: To run the application, change the directory to the folder created:
In the terminal, you can see that the application is compiled successfully.
Step 3: Open your browser on http://localhost:4200/. You can see the output as shown below.
Code:
<label for="email"><b>Email</b></label><pre></pre>
<input type="text" placeholder="Enter Email" name="email" id="email"
required><pre></pre>
<label for="psw"><b>Password</b></label><pre></pre>
<input type="password" placeholder="Enter Password" name="psw" id="psw"
required><pre></pre>
<label for="age"><b>Age</b></label><pre></pre>
<input type="text" placeholder="Enter age" name="age" id="age"
required><pre></pre>
<hr>
<button type="submit" class="registerbtn">Register</button>
</div>
</form>
</body>
</html>
Step 5: To save the changes in the code, click File > Save. Now, open browser to see the application.
Output:
Step 6: Open app.component.css file and add different elements and properties to style the application.
Code:
input[type=text], input[type=password] {
width: 50%;
padding: 15px;
margin: 5px 0 22px 0;
display: inline-block;
border: none;
background: #f1f1f1;
}
Output:
Angular Fundamentals
• Components define views, which are sets of screen elements that Angular can choose among and modify
according to your program logic and data
• Components use services, which provide specific functionality not directly related to views. Service providers
can be injected into components as dependencies, making your code modular, reusable, and efficient.
Modules, components and services are classes that use decorators. These decorators mark their type and provide
metadata that tells Angular how to use them.
• The metadata for a component class associates it with a template that defines a view. A template combines
ordinary HTML with Angular directives and binding markup that allow Angular to modify the HTML before
rendering it for display.
• The metadata for a service class provides the information Angular needs to make it available to components
through dependency injection (DI)
An application's components typically define many views, arranged hierarchically. Angular provides the Router service
to help you define navigation paths among views. The router provides sophisticated in-browser navigational capabilities.
Metadata
• Metadata tells Angular how to process a class. To tell Angular that Course Component is a component, metadata
is attached to the class. In TypeScript, you attach metadata by using a decorator. In the below code, you can see
metadata attached to the Course Component:
• Here is the @Component decorator, which identifies the class immediately below it as a component class. The
@Component decorator takes the required configuration object which Angular needs to create and present the
component and its view.
Module Overview
In this module, students will be able to learn about frontend technologies such as HTML5, CSS3, Bootstrap, JavaScript
and TypeScript.
Module Objective
At the end of this module, students should be able to demonstrate appropriate knowledge, and show an
understanding of the following:
Component Basics
- Nesting Components
- Data Binding - Property & Event Binding, String Interpolation, Style binding
Component Basics
Components are the main building block for Angular applications. Each component consists of:
The above image gives the tree structure of classification. There’s a root component, which is the AppComponent, that
then branches out into other components creating a hierarchy.
Every Angular application has at least one component, the root component that connects a component hierarchy with
the page document object model (DOM). Each component defines a class that contains application data and logic, and
is associated with an HTML template that defines a view to be displayed in a target environment.
Let’s have a look at each of the files Inside the src/app folder and understand their role in the Angular project.
In the above screenshot, you can see that there are a total of 6 files as of now inside the src/app folder.
app.module.ts: This is the main module file for the project. Each Angular project is divided into modules to make the
project management easy. By default, the whole project is a part of a single module but you can always create more
modules. A module is a logical chunk of project resources that works independently or in combination with other
modules. This file contains a module called AppModule.
app.component.html: This file is the template file for the one and only component in our project as of now. This
component is called the AppComponent. The extension html indicated that this file is an HTML document and will define
the view of the component.
app.component.css: This file work in combination with the HTML template and adds CSS styles to the HTML elements
defined in that template. This only only contains CSS classes and styles.
app.component.ts: This is the main class file for the AppComponent component. This file contains the TypeScript class
for the component and all the business logic for this component goes inside this file.
app.component.spec.ts: This file is for unit testing the AppComponent component. Let’s not worry about this for now.
Feel free to delete the file if it bothers you too much.
app-routing.module.ts: This is another module file for the project (just like the app.module.ts that contains the module
AppModule) that handles routing or navigation for the whole project. It defines how different components will be
presented to the user as the user navigates within the application.
Component Lifecycle
Components are core building blocks of Angular applications. Each component is instantiated when it is required, it does
its job and then gets destroyed to free us the memory. Component instances have a lifecycle as Angular creates, updates,
and destroys them. Developers can tap into key moments in that lifecycle by implementing one or more of the lifecycle
hook interfaces in the Angular core library.
For example, we may want to make a call to an external API as soon as a component finished loading or we may want
to notify a web-service when a component is destroyed. We can do this with the help of lifecycle hooks.
Here is some of the important lifecycle hooks that Angular provides for the components in the same sequence in which
they are called after the constructor of the component class is executed.
Open the file src/app/app/component.ts and there is the code for the TypeScript class responsible for the
AppComponent.
In the above code, you can see that we have a class called AppComponent that has a member variable defined inside it.
This class does not have a constructor defined, but we can always create a constructor manually as shown below.
The code inside the constructor is executed as soon as the class is initialized.
Setting up templates
A template is a form of HTML that tells Angular how to render the component. Templates in Angular
represent a view whose role is to display data and change the data whenever an event occurs. It’s default
language for templates is HTML.
A template looks like regular HTML, except that it also contains Angular template syntax, which alters the
HTML based on your application's logic and the state of application and DOM data. Your template can use
data binding to coordinate the application and DOM data, pipes to transform data before it is displayed,
and directives to apply application logic to what gets displayed.
Types of Templates
There are two ways of defining a template in an angular component.
1. Inline Template
The inline template is defined by placing the HTML code in backticks ` and is linked to the component metadata using
the template property of @Component decorator.
Code:
import { Component } from '@angular/core';
Output:
2. External Template
The template is defined in a separate HTML file and is linked to the component metadata using
the @Component decorator’s templateUrl property.
expense-manager.component.html
<html>
<h2>Welcome to Edubridge!</h2>
</html>
expense-manager.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
constructor() { }
ngOnInit(): void {
}
}
Output:
Activity Four
Angular CLI will generate 4 files for the component in the src/app folder of your project:
Angular CLI will generate 4 files for the component in the src/app folder of your project:
Note:
We can also customize where the component's files are placed. Angular CLI adds the component
to the declarations array of the module.
@NgModule({
// [...]
declarations: [ AppComponent, HomeComponent ]
// [...]
})
export class AppModule { }
Activity Five
Nesting Components
Once you type the above command and press the enter button, then it will create a folder called student within the app
folder with four files as shown in the below image.
As you can see in the above code, here we are using the inline template to display the page header as it contains only
three lines of code. But if you want then you can also use an external template by using the templateUrl property of
@Component decorator.
Running Angular Application:
In order to compile and run the angular application with your default browser, type ng serve -o and press the enter key
as shown below.
Once you type the above command, it will compile and run your application using your default browser. If you observe
the output, you are only getting the header, not the student details as shown in the below image.
This is because we have created the child component i.e. the StudentComponent but not yet used it within the parent
component i.e. within the AppComponent. So, in order to display the Student details, you need to nest the
StudentComponent inside the AppComponent.
Step 3: Open your parent component i.e. “app.component.ts” file and then include “app-student” as a directive as
shown in the below image. If you remember, the “app-student” that we used here is nothing but a selector
of StudentComponent i.e. our child component.
app.component.ts
In order to style the table, please add the following styles in the styles.css file which is present inside the src folder.
table {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size:large;
border-collapse: collapse;
}
td {
border: 1px solid black;
}
With the above changes in place, now you should see the student details along with the header as expected as shown
in the below image.
Activity Six
Two-way data binding, on the other hand, allows synchronization of data in such a way that the views can be updated
using the models and the models can be updated using views. This means that your application will be able to share
information between a component class and its template.
Interpolation binding is used to return HTML output from TypeScript code i.e. from the components to the
views. Here, the template expression is specified within double curly braces. Through Interpolation, strings
can be added into the text that is present between HTML element tags and within attribute assignments.
These strings are calculated using Template expressions.
Example:
app.component.html
<h1>{{title}}</h1>
Learn <b> {{course}}
</b> with me.
4 * 2 = {{4 * 2}}
<div><img src="{{image}}"></div>
app.component.ts
export class AppComponent {
title = 'Databinding';
course ='Angular';
image = 'paste the url here'
constructor(){}
}
Activity Seven
Property Binding
In Property binding, value flows from a component’s property into the target elements property. Therefore, Property
binding can’t be used to read or pull data from the target elements or to call a method that belongs to the target
element. The events raised by the element can be acknowledged through event binding which will be covered later on
in this article.
In general, one can say that the component property value will be set to the element property using Property binding.
<h1>Property binding</h1>
<div><img [src]="image"></div>
In the above example, the src property of the image element is bound to a component’s image property.
Please make a note that when you need to set element properties to non-string data values, you must use Property
binding and not Interpolation.
Event Binding
The Event binding feature lets you listen to certain events such as mouse movements, keystrokes, clicks, etc. In Angular,
event binding can be achieved by specifying the target event name within regular brackets on the left of an equal to ( =
) sign, and the template statement on the right side within quotes (” “).
Code:
<div>
<button (click)="goBack()">Go back</button>
</div>
The ‘click‘ in the above example is the target events name and ‘goBack()’ is the template statement.
Output:
Whenever event binding occurs, an event handler will be set by Angular for the target event. When that particular event
gets raised, the template statement is executed by the handler. Generally, receivers are involved with template
statements that perform actions in response to the event. Here, binding is used to convey information about the event.
These data values of the information include event string, object, etc.
The syntax of two way binding is – [( )]. As you can see, it is a combination of the property binding syntax i.e. [ ] and the
event binding syntax ( ). According to Angular, this syntax resembles “Banana in a Box”.
Code:
<label ><b>Name:</b>
<input [(ngModel)]="course.name" placeholder="name"/>
</label>
When you execute this code, you will see that changes to either the models or the views will result in changes
to the corresponding views and models. Take a look at the image below that shows the name of the course
being changed from ‘Python’ to ‘Pytho’ from the views:
Example:
A single property userName in the component.
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'myapp';
userName = "Rita";
constructor(){}
}
app.component.html
<div class="container">
<div class="row">
<div class="col-sm-6">
In the template as you can see target of two-way binding is ngModel directive and
the expression is the property “userName” property of the component.
@NgModule({
declarations: [
AppComponent,
],
imports: [
AppRoutingModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
Activity Eight
@Input() and @Output() allow Angular to share data between the parent context and child directives or
components. An @Input() property is writable while an @Output() property is observable.
<parent-component>
<child-component></child-component>
</parent-component>
Here, the <child-component> selector, or child directive, is embedded within a <parent-component>, which serves as
the child's context.
@Input() and @Output() act as the API, or application programming interface, of the child component in that they allow
the child to communicate with the parent. Think of @Input() and @Output() like ports or doorways—@Input() is the
doorway into the component allowing data to flow in while @Output() is the doorway out of the component, allowing
Note:
@Input() and @Output() are independent
Though @Input() and @Output() often appear together in apps, you can use them separately. If the nested
component is such that it only needs to send data to its parent, you wouldn't need an @Input(), only an
@Output(). The reverse is also true in that if the child only needs to receive data from the parent, you'd only
need @Input().
In the child
To use the @Input() decorator in a child component class, first import Input and then decorate the property
with @Input():
<p>
Today's item: {{item}}
</p>
In the Parent
The next step is to bind the property in the parent component's template. In this example, the parent component
template is app.component.html.
First, use the child's selector, here <app-item-detail>, as a directive within the parent component template. Then,
use property binding to bind the property in the child to the property of the parent.
<app-item-detail [item]="currentItem"></app-item-detail>
Next, in the parent component class, app.component.ts, designate a value for currentItem:
export class AppComponent {
currentItem = 'Television';
}
With @Input(), Angular passes the value for currentItem to the child so that item renders as Television.
Output:
The key takeaway is that when binding to a child component's property in a parent component—that is, what's
in square brackets—you must decorate the property with @Input() in the child component.
Activity Nine
An @Output() property should normally be initialized to an Angular EventEmitter with values flowing out of the
component as events.
What is EventEmitter?
EventEmitter is responsible for raising the event. The @output property normally is of type EventEmitter. The child
component will use the emit() method to emit an event along with the data.
@Output() marks a property in a child component as a doorway through which data can travel from the child to the
parent. The child component then has to raise an event so the parent knows something has changed. To raise an
event, @Output() works hand in hand with EventEmitter, which is a class in @angular/core that you use to emit custom
events.
Note:
The HTML element <input> and the Angular decorator @Input() are different. This documentation is
about component communication in Angular as it pertains to @Input() and @Output().
The following example shows how to set up an @Output() in a child component that pushes data you enter in an
HTML <input> to an array in the parent component.
In the child
This example features an <input> where a user can enter a value and click a <button> that raises an event.
The EventEmitter then relays the data to the parent component.
First, be sure to import Output and EventEmitter in the child component class:
Next, still in the child, decorate a property with @Output() in the component class. The following
example @Output() is called newItemEvent and its type is EventEmitter, which means it's an event.
• @Output()—a decorator function marking the property as a way for data to go from the child to the parent
• newItemEvent—the name of the @Output()
• EventEmitter<string>—the @Output()'s type
• new EventEmitter<string>()—tells Angular to create a new event emitter and that the data it emits is of type
string. The type could be any type, such as number, boolean, and so on. For more information on EventEmitter,
see the EventEmitter API documentation.
addNewItem(value: string) {
this.newItemEvent.emit(value);
}
}
The addNewItem() function uses the @Output(), newItemEvent, to raise an event in which it emits the value the user
types into the <input>. In other words, when the user clicks the add button in the UI, the child lets the parent know
about the event and gives that data to the parent.
In the child's template
• The child's template has two controls. The first is an HTML <input> with a template reference
variable , #newItem, where the user types in an item name. Whatever the user types into the <input> gets
stored in the #newItem variable.
• The second element is a <button> with an event binding. You know it's an event binding because the part to the
• The (click) event is bound to the addNewItem() method in the child component class which takes as its
argument whatever the value of #newItem is.
• Now the child component has an @Output() for sending data to the parent and a method for raising an event.
The next step is in the parent.
In the parent
In this example, the parent component is AppComponent, but you could use any component in which you could nest
the child.
The AppComponent in this example features a list of items in an array and a method for adding more items to the array.
addItem(newItem: string) {
this.items.push(newItem);
}
}
The addItem() method takes an argument in the form of a string and then pushes, or adds, that string to the items array.
Next, in the parent's template, bind the parent's method to the child's event. Put the child selector, here <app-item-
output>, within the parent component's template, app.component.html.
<app-item-output (newItemEvent)="addItem($event)"></app-item-
output>
The event binding, (newItemEvent)='addItem($event)', tells Angular to connect the event in the child, newItemEvent,
to the method in the parent, addItem(), and that the event that the child is notifying the parent about is to be the
argument of addItem(). In other words, this is where the actual hand off of data takes place. The $event contains the
data that the user types into the <input> in the child template UI.
Now, in order to see the @Output() working, add the following to the parent's template:
The *ngFor iterates over the items in the items array. When you enter a value in the child's <input> and click the
button, the child emits the event and the parent's addItem() method pushes the value to the items array and it
renders in the list.
Output:
After adding the new item the output looks like this:
Activity Ten
The target, item, which is an @Input() property in the child component class, receives its value from the parent's
property, currentItem. When you click delete, the child component raises an event, deleteRequest, which is the
argument for the parent's crossOffItem() method.
The following diagram is of an @Input() and an @Output() on the same child component and shows the different parts
of each:
As the diagram shows, use inputs and outputs together in the same manner as using them separately. Here, the child
selector is <app-input-output> with item and deleteRequest being @Input() and @Output() properties in the child
component class. The property currentItem and the method crossOffItem() are both in the parent component class.
To combine property and event bindings using the banana-in-a-box syntax, [()], see Two-way Binding.
While declaring inputs and outputs in the @Directive and @Component metadata is possible, it is a better practice to
use the @Input() and @Output() class decorators instead, as follows:
Note:
If you get a template parse error when trying to use inputs or outputs, but you know that the
properties do indeed exist, double-check that your properties are annotated
with @Input() / @Output() or that you've declared them in an inputs/outputs array:
Exercise
Answer the following questions.
Templates
We have learnt in the last module that a template is a form of HTML that tells Angular how to render the component.
There are two ways of defining a template in an angular component.
• Inline template: The inline template is defined by placing the HTML code in backticks ` and is linked to the
component metadata using the template property of @Component decorator.
• External Template: The template is defined in a separate HTML file and is linked to the component metadata
using the @Component decorator’s templateUrl property.
Angular 7 uses the <ng-template> as the tag instead of <template>which is used in Angular2. The reason it started to
use <ng-template> instead of <template> from Angular 4 onwards is because there is a name conflict between the
<template> tag and the html <template> standard tag. It will deprecate completely going ahead. This was one of the
major changes made in Angular 4 version.
Let us now use the template along with the if else condition and see the output.
app.component.html
<div> Months :
<select (change) = "changemonths($event)" name = "month">
<option *ngFor = "let i of months">{{i}}</option>
</select>
</div>
<br/>
<div>
<span *ngIf = "isavailable;then condition1 else condition2">
Condition is valid.
For the Span tag, we have added the if statement with the else condition and will call template condition1, else
condition2.
If the condition is true, then the condition1 template is called, otherwise condition2.
app.component.ts
myClickFunction(event: any) {
//just added console.log which will display the event details in browser on click of
the button.
alert("Button is clicked");
console.log(event);
}
changemonths(event: any) {
The variable isavailable is false so the condition2 template is printed. If you click the button, the respective template
will be called.
app.component.ts
myClickFunction(event: any) {
this.isavailable = !this.isavailable;
When you click on the button based on the value of the isavailable variable the respective template will be displayed −
If you inspect the browser, you will see that you never get the span tag in the dom. The following example will help you
understand the same.
We do not see the span tag and also the <ng-template> in the dom structure when we inspect the same in browser.
The following line of code in html will help us get the span tag in the dom −
<div> Months :
<select (change) = "changemonths($event)" name = "month">
<option *ngFor = "let i of months">{{i}}</option>
</select>
</div>
<br/>
<div>
<span *ngIf = "isavailable; else condition2">
Condition is valid.
</span>
<ng-template #condition1>Condition is valid from template </ng-template>
<ng-template #condition2>Condition is invalid from template</ng-template>
If we remove the then condition, we get the “Condition is valid” message in the browser and the span tag is also available
in the dom. For example, in app.component.ts, we have made the isavailable variable as true.
Styles
Angular applications are styled with standard CSS. That means you can apply everything you 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.
An Angular component ideally consists of the presentation file, the style sheet, the component file itself and the test
file. This means that for every component created or generated by the CLI there is a specific style sheet for it. Angular
was built in such a way that the styles defined inside the component style sheet are scoped to only that component
alone no matter the class name. This is a lot like local and global variable definition and how they are scoped; this scoping
mechanism is known as encapsulation
For every Angular component you write, you can define not only an HTML template, but also the CSS styles that go with
that template, specifying any selectors, rules, and media queries that you 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. Usually you give it one string, as in the following example:
@Component({
selector: 'app-root',
Special selectors
Component styles have a few special selectors from the world of shadow DOM style scoping. The following sections
describe these selectors.
• :host
Use the :host pseudo-class selector to target styles in the element that hosts the component (as opposed to targeting
elements inside the component's template).
:host {
display: block;
border: 1px solid black;
}
The :host selector is the only way to target the host element. You can't reach the host element from inside the
component with other selectors because it's not part of the component's own template. The host element is in a parent
component's template.
Use the function form to apply host styles conditionally by including another selector inside parentheses after :host.
The next example targets the host element again, but only when it also has the active CSS class.
:host(.active) {
border-width: 3px;
}
Sometimes it's useful to apply styles based on some condition outside of a component's view. For example, a CSS theme
class could be applied to the document <body> element, and you want to change how your component looks based on
that.
Use the :host-context() pseudo-class selector, which works just like the function form of :host(). The :host-context()
selector looks for a CSS class in any ancestor of the component host element, up to the document root. The :host-
context() selector is useful when combined with another selector.
The following example applies a background-color style to all <h2> elements inside the component, only if some
ancestor element has the CSS class theme-light.
:host-context(.theme-light) h2 {
background-color: #eef;
}
• /deep/
Component styles normally apply only to the HTML in the component's own template.
Use the /deep/ selector to force a style down through the child component tree into all the child component views. The
/deep/ selector works to any depth of nested components, and it applies to both the view children and content children
of the component.
The following example targets all <h3> elements, from the host element down through this component to all of its child
elements in the DOM.
:host /deep/ h3 {
font-style: italic;
}
Styles in metadata
You can add a styles array property to the @Component decorator. Each string in the array (usually just one string)
defines the CSS.
@Component({
selector: 'hero-app',
template: `
<h1>Tour of Heroes</h1>
<hero-app-main [hero]=hero></hero-app-main>`,
styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}
You can load styles from external CSS files by adding a styleUrls attribute into a component's @Component decorator:
@Component({
selector: 'hero-details',
template: `
<h2>{{hero.name}}</h2>
<hero-team [hero]=hero></hero-team>
<ng-content></ng-content>
`,
styleUrls: ['app/hero-details.component.css']
})
export class HeroDetailsComponent {
/* . . . */
}
You can embed styles directly into the HTML template by putting them inside <style> tags.
@Component({
selector: 'hero-controls',
template: `
<style>
button {
background-color: white;
border: 1px solid #777;
}
</style>
<h3>Controls</h3>
<button (click)="activate()">Activate</button>
`
})
You can also embed <link> tags into the component's HTML template.
As with styleUrls, the link tag's href URL is relative to the application root, not the component file.
@Component({
selector: 'hero-team',
template: `
<link rel="stylesheet" href="app/hero-team.component.css">
<h3>Team</h3>
<ul>
<li *ngFor="let member of hero.team">
{{member}}
</li>
</ul>`
})
CSS @imports
In this case, the URL is relative to the CSS file into which you're importing.
@import 'hero-details-box.css';
View encapsulation
Encapsulation is a very critical aspect of the modern web components standard which supports keeping every
component modular and independent. The shadow DOM is a part of the modern web component standard that ensures
encapsulation is carried out through its API, providing a way to attach a separated DOM to an element. So basically, the
shadow DOM allows you to hide DOM logic behind other elements without affecting any other part of the application
so that you can use scoped styles in your component in isolation.
View encapsulation defines whether the template and styles defined within the component can affect the whole
application or vice versa. Angular provides three encapsulation strategies:
Emulated (default) - styles from main HTML propagate to the component. Styles defined in this component's
@Component decorator are scoped to this component only.
ShadowDOM - styles from main HTML do not propagate to the component. Styles defined in this
None - styles from the component propagate back to the main HTML and therefore are visible to all components on the
page. Be careful with apps that have None and Native components in the application. All components with None
encapsulation will have their styles duplicated in all components with Native encapsulation.
Example Application
app.component.ts
@Component({
<h1>{{title}}</h1>
<p>I am a paragraph in green</p>
src/styles.css
p {color: green;}
Run the app and you should able to see the paragraph in green.
Open the chrome developer tools and check the elements section. The CSS rules are inserted in the head section of
the page.
The ViewEncapsulation.None is used, when we do not want any encapsulation. When you use this, the styles defined in
one component affects the elements of the other components.
@Component({
selector: 'app-none',
template: `<p>I am not encapsulated and in blue
(ViewEncapsulation.None) </p>`,
styles: ['p { color:blue}'],
encapsulation: ViewEncapsulation.None
})
We have added encapsulation: ViewEncapsulation.None. We have also defined the inline style p { color:blue}
Do not forget to import & declare the component in AppModule. You also need to add the <app-none></app-none>
selector in app.component.html
<h1>{{title}}</h1>
<p>I am a paragraph in green</p>
<app-none></app-none>
Run the code and as expected both the paragraphs turn blue.
That is because, the global scope of CSS styles. The style defined in the ViewNoneComponent is injected to the global
style and overrides any previously defined style. The style p {color: blue;} overrides the style p {color: green;} defined in
the styles.css.
ViewEncapsulation.Emulated
In a HTML page, we can easily add a id or a class to the element to increase the specificity of the CSS rules so that the
CSS rules do not interfere with each other..
The ViewEncapsulation.Emulated strategy in angular adds the unique HTML attributes to the component CSS styles and
to the markup so as to achieve the encapsulation. This is not true encapsulation. The Angular Emulates the
encapsulation, Hence the name Emulated.
Create a new component in Angular app and name it as ViewEmulatedComponent. as shown below:
We have not added any id in the above component. Only change this component has with one ViewNoneComponent
was encapsulation mode, which is set to ViewEncapsulation.Emulated
Update app.component.html
<h1>{{title}}</h1>
<app-none></app-none>
<app-emulated></app-emulated>
Now, you can see that the style does not spill out to other components, when you use emulated mode. i.e because
angular adds _ngcontent-c# attributes to the emulated components and makes necessary changes in the generated
styles
_ngcontent-c2 attribute is added in the style and to the p element, making the style local to the component
<style>p[_ngcontent-c2] { color:red}</style>
• This strategy isolates the component styles. They do not bleed out to other components.
• The global styles may affect the element styles in the component
• The Angular adds the attributes to the styles and mark up
ViewEncapsulation.ShadowDOM
The Shadow DOM is a scoped sub-tree of the DOM. It is attached to a element (called shadow host) of the DOM tree.
The shadow dom do not appear as child node of the shadow host, when you traverse the main DOM.
The browser keeps the shadow DOM separate from the main DOM. The rendering of the Shadow dom and the main
DOM happens separately. The browser flattens them together before displaying it to the user. The feature, state & style
of the Shadow DOM stays private and not affected by the main DOM. Hence it achieves the true encapsulation.
@Component({
selector: 'app-shadowdom',
template: `<p>I am encapsulated inside a Shadow DOM ViewEncapsulation.ShadowDom</p>`,
styles: ['p { color:brown}'],
encapsulation: ViewEncapsulation.ShadowDom
})
export class ViewShadowdomComponent {
Activity Eleven
Follow the instructions:
Adding Bootstrap
What is Bootstrap?
Bootstrap is the most popular front-end open-source CSS framework and a toolkit to design your customized
and mobile-first responsive websites. It comes with CSS- and JavaScript-based design templates, Sass variables
and mixins, a responsive grid system, extensive prebuilt components, and powerful JavaScript plugins for
typography, forms, buttons, navigations, carousels, slides, and many other interface components.
In this step, we will add Bootstrap to your Angular project. There are many ways to install Bootstrap into your
Angular project.
We will use the first method and install Bootstrap through npm in the command line interface.
This command will add the bootstrap package to package.json. Also, it will install bootstrap assets in the
node_modules/bootstrap folder.
You need to install jQuery next. Let's use the following command in the command-line interface:
• Using angular.json
• Using index.html
• Using styles.css
• Using ng-bootstrap and ngx-bootstrap
• Using Schematics
You can add Bootstrap to Angular by including the below files in your angular.json file:
As shown below:
After adding these tags, you can see your src/index.html file like the below example:
my-app/src/index.html
Also, you can add Bootstrap to your Angular project by importing the bootstrap.css file in your src/styles.css
file as follows:
my-app/src/styles.css
In this method, ng-bootstrap completely replaces JavaScript implementation for components. You don't have
to add bootstrap.js or bootstrap.min.js. Also, you should not include jQuery or popper.js libraries when you
follow this method to add Bootstrap to your Angular project.
After that, you should import the main module and add it to your app root module as shown below:
my-app/src/app/app.modules.ts
my-app/angular.json
Also, you can use the ngx-bootstrap library to add Bootstrap to your Angular project. First, you have to install ngx-
bootstrap to your project as follows:
After that, you should add the Bootstrap CSS file. You can include Bootstrap from CDN within the <head> tag in the
index.html file, as shown below.
my-app/src/index.html
my-app/src/app/app.module.ts
Because ngx-bootstrap provides each component with its module, you need to import the required modules to your
project. In this way, you can import only the components required for your project and make the application size smaller.
With the new ng add command in Angular 7+, it's straightforward to add support to an external library to your project.
Using this command, you can add Bootstrap to Angular without extra configurations. You have just to run the below
command in the terminal screen as shown in the below example:
Directives
Directives are classes that add additional behavior to elements in your Angular applications. Use Angular's built-in
directives to manage forms, lists, styles, and what users see.
Components Used with a template. This type of directive is the most common directive type.
Attribute directives Change the appearance or behavior of an element, component, or another directive.
Structural directives Change the DOM layout by adding and removing DOM elements.
Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components.
Many NgModules such as the RouterModule and the FormsModule define their own attribute directives. The most
common attribute directives are as follows:
On the element you'd like to style, add [ngClass] and set it equal to an expression. In this case, isSpecial is a boolean set
to true in app.component.ts. Because isSpecial is true, ngClass applies the class of special to the <div>.
1. To use NgClass with a method, add the method to the component class. In the following example,
setCurrentClasses() sets the property currentClasses with an object that adds or removes three classes based
on the true or false state of three other component properties.
Each key of the object is a CSS class name. If a key is true, ngClass adds the class. If a key is false, ngClass removes the
class.
2. In the template, add the ngClass property binding to currentClasses to set the element's classes:
For this use case, Angular applies the classes on initialization and in case of changes. The full example calls
setCurrentClasses() initially with ngOnInit() and when the dependent properties change through a button click. These
steps are not necessary to implement ngClass. For more information, see the live example / download example
app.component.ts and app.component.html.
Use NgStyle to set multiple inline styles simultaneously, based on the state of the component.
In the following example, setCurrentStyles() sets the property currentStyles with an object that defines three styles,
based on the state of three other component properties.
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
Use the NgModel directive to display a data property and update that property when the user makes changes.
imports: [
BrowserModule,
FormsModule // <--- import into the NgModule
],
/* . . . */
})
export class AppModule { }
2. Add an [(ngModel)] binding on an HTML <form> element and set it equal to the property, here name.
<label for="example-ngModel">[(ngModel)]:</label>
<input [(ngModel)]="currentItem.name" id="example-ngModel">
To customize your configuration, write the expanded form, which separates the property and event binding. Use
property binding to set the property and event binding to respond to changes. The following example changes the
<input> value to uppercase:
This section walks you through creating a highlight directive that sets the background color of the host element to
yellow.
2. Import ElementRef from @angular/core. ElementRef grants direct access to the host DOM element through its
nativeElement property.
3. Add ElementRef in the directive's constructor() to inject a reference to the host DOM element, the element to
which you apply applyCSSClass.
4. Add logic to the ApplyClassDirective class that sets the background to yellow.
1. To use the ApplyClassDirective, add a <p> element to the HTML template with the directive as an attribute.
Src/app/app.component.html
Angular creates an instance of the ApplyClassDirective class and injects a reference to the <p> element into the
directive's constructor, which sets the <p> element's background style to yellow.
This section shows you how to detect when a user enters into or out of the element and to respond by setting or clearing
the highlight color.
2. Add two event handlers that respond when the mouse enters or leaves, each with the @HostListener()
decorator.
Subscribe to events of the DOM element that hosts an attribute directive, the <p> in this case, with the
@HostListener() decorator.
Host Binding binds a Host element property to a variable in the directive or component.
As well as listening to output events from the host element a directive can also bind to input properties in the host
element with @HostBinding.
This directive can change the properties of the host element, such as the list of classes that are set on the host element
as well as a number of other properties.
Using the @HostBinding decorator a directive can link an internal property to an input property on the host element.
So, if the internal property changed the input property on the host element would also change.
We first need something, a property on our directive which we can use as a source for binding.
We’ll create a boolean called ishovering and in our onMouseOver() and onMouseOut() functions we’ll set this to true
and false accordingly, like so:
HostBinding Example
The following appHighLight directive, uses the HostBinding on style.border property of the parent element to the border
property.
Whenever we change the value of the border, the angular will update the border property of the host element.
Now we need to link this source property to an input property on the host element, we do this by decorating our
ishovering boolean with the @HostBinding decorator.
The @HostBinding decorator takes one parameter, the name of the property on the host element which we want
to bind to.
If you remember we can use the alternative ngClass syntax by binding to the [class.<class-name>] property. Let’s
add the card-outline-primary class to our host element when the ishovering boolean is true.
Now when we hover over a card as well as the punchline showing we adding a blue border to the card.
Angular Pipes allows its users to change the format in which data is being displayed on the screen. For instance,
consider the date format. Dates can be represented in multiple ways, and the user can decide which one to use with
the help of Angular Pipes.
Angular Pipes transform the output. You can think of them as makeup rooms where they beautify the data into a
more desirable format. They do not alter the data but change how they appear to the user.
Technically, pipes are simple functions designed to accept an input value, process, and return a transformed value
as the output. Angular supports many built-in pipes. However, you can also create custom pipes that suit your
requirements. Some salient features include:
As mentioned above, Angular provides several built-in pipes to beautify the data being shown on the user interface.
In the pipes.component.ts file, we’ve created properties for date and name.
@Component({
selector: 'app-pipes',
templateUrl: './pipes.component.html',
styleUrls: ['./pipes.component.css']
})
dateToday: string;
name: string;
constructor() { }
ngOnInit(): void {
this.name = "Simplilearn"
In Pipes.component.html, we’ve interpolated the properties and used pipes to format them.
</h1>
In the code mentioned above, the date property initially displays in the default format. However, when used with
the date pipe, the format changes. We’ve also used other pipes like uppercase and lowercase for better
understanding.
As you can see, we have used the slice pipe for the name property. This pipe slices the text and displays it from the
index position provided by the user.
Now that you know how to use pipes and their functionalities, let us show you how to create custom pipes.
Pipes in Angular are classified into Pure and Impure types. Let’s have a closer look at them.
Pure Pipes
Impure Pipes
An impure pipe in Angular is called for every change detection cycle regardless of the change in the input fields. Multiple
pipe instances are created for these pipes and the inputs passed to these pipes are mutable.
Although by default pipes are pure, you can specify impure pipes using the pure property as shown below.
@Pipe({
name: 'demopipe',
pure : true/false
})
Angular makes provision to create custom pipes that convert the data in the format that you desire. Angular Pipes are
TypeScript classes with the @Pipe decorator. The decorator has a name property in its metadata that specifies the Pipe
and how and where it is used.
Attached below is a screenshot of the code that Angular has for the uppercase pipe.
Pipe implements the PipeTransform interface. As the name suggests, it receives the value and transforms it into the
desired format with the help of a transform() method.
ng g pipe <nameofthepipe>
Example:
@Pipe({
name: 'demopipe'
})
return null;
As you can see, the PipeTransform interface and the transform method have been created.
Activity Twelve
Services provides specific functionality in an Angular application. In a given Angular application, there may be one or
more services can be used. Similarly, an Angular component may depend on one or more services.
Also, Angular services may depend on other services to work properly. Dependency resolution is one of the complex
and time-consuming activity in developing any application. To reduce the complexity, Angular provides Dependency
Injection pattern as one of the core concepts.
There are three types of Dependency Injections in Angular, they are as follows:
An Angular service is plain Typescript class having one or more methods (functionality) along with @Injectable
decorator. It enables the normal Typescript class to be used as service in Angular application.
Here, @Injectable decorator converts a plain Typescript class into Angular service.
To use Dependency Injection, every service needs to be registered into the system. Angular provides multiple option to
register a service. They are as follows −
ModuleInjector @ root
ModuleInjector enforces the service to used only inside a specific module. ProvidedInmeta data available in @Injectable
has to be used to specify the module in which the service can be used.
The value should refer to the one of the registered Angular Module (decorated with @NgModule). root is a special
option which refers the root module of the application. The sample code is as follows −
ModuleInjector @ platform
Platform Injector is one level higher than ModuleInject and it is only in advanced and rare situation. Every Angular
application starts by executing PreformBrowserDynamic().bootstrap method (see main.js), which is responsible for
bootstrapping root module of Angular application.
PreformBrowserDynamic() method creates an injector configured by PlatformModule. We can configure platform level
services using platformBrowser() method provided by PlatformModule.
NullInjector
NullInjector is one level higher than platform level ModuleInjector and is in the top level of the hierarchy. We could not
able to register any service in the NullInjector. It resolves when the required service is not found anywhere in the
hierarchy and simply throws an error.
ElementInjector enforces the service to be used only inside some particular components. providers and ViewProviders
meta data available in @Component decorator is used to specify the list of services to be visible for the particular
component. The sample code to use providers is as follows −
ExpenseEntryListComponent
// import statement
import { DebugService } from '../debug.service';
// component decorator
@Component({
selector: 'app-expense-entry-list',
templateUrl: './expense-entry-list.component.html',
styleUrls: ['./expense-entry-list.component.css'],
providers: [DebugService] })
viewProviders is similar to provider except it does not allow the service to be used inside the component’s content
created using ng-content directive.
ExpenseEntryListComponent
// import statement
import { DebugService } from '../debug.service';
// component decorator
@Component({
selector: 'app-expense-entry-list',
templateUrl: './expense-entry-list.component.html',
styleUrls: ['./expense-entry-list.component.css'], viewProviders:
[DebugService]
})
Parent component can use a child component either through its view or content. Example of a parent component with
child and content view is mentioned below −
<div>
child template in view
<child></child>
</div>
<ng-content></ng-content>
<div>
child template in view
</div>
Here,
• child component is used in two place. One inside the parent’s view. Another inside parent content.
• Services will be available in child component, which is placed inside parent’s view.
• Services will not be available in child component, which is placed inside parent’s content.
Example:
we'll create a service class and inject the same into a component that displays a button for the user. The service holds
employee details such as name, employee ID, and email ID. When the user clicks on the display button, the same will be
displayed.
Step 1: Create a component to display the employee records. Use the command ng g c <component name> for the
same. The component we’ve created is called emp_info
Step 2: Create a service using the command, ng g service <service name>. We’ve created a service called records. Once
run, two files records.service.ts and records.service.spec.ts are created. The service consists of the employee data that
needs to be displayed. We will be using three arrays for this purpose.
With the agenda to retrieve this data in our component, we use a method, for the same. This method returns the
employee data.
return this.info1
getInfo2():string[]{
return this.info2
getInfo3():string[]{
return this.info3
Step 3: In order to retrieve this information in our emp_info.component.ts, we need three more arrays.
infoReceived1: string[]=[];
infoReceived2: string[]=[];
infoReceived3: string[]=[];
getInfoFromService1(){
this.infoReceived1 = this.rservice.getInfo1()
getInfoFromService2(){
this.infoReceived2 = this.rservice.getInfo2()
getInfoFromService3(){
this.infoReceived3 = this.rservice.getInfo3()
As mentioned, services are implemented using dependency injection. We import the service class into the
component.ts file. The key reason behind doing this is to tell Angular that when the component is created, an instance
@Component({
selector: 'app-e-info',
templateUrl: './e-info.component.html',
providers: [RecordsService]
})
infoReceived1: string[]=[];
infoReceived2: string[]=[];
infoReceived3: string[]=[];
getInfoFromService1(){
this.infoReceived1 = this.rservice.getInfo1()
getInfoFromService2(){
this.infoReceived2 = this.rservice.getInfo2()
getInfoFromService3(){
this.infoReceived3 = this.rservice.getInfo3()
ngOnInit(): void { }}
Now that you’ve learned how to create the service and inject it into the components, let’s move on to the UI of the
application. We’re creating a button for each employee.
Step 4: In the component.html file, we are creating an unordered list. We are also using the *ngFor directive to loop
over the record fields.
<ul class="list-group">
</ul>
<ul class="list-group">
</ul>
<ul class="list-group">
</ul>
Once you run the application using the ng serve command, the output looks like this:
Activity Thirteen
Let us see how a component can resolve a service using the below flow diagram.
• First, component tries to find the service registered using viewProviders meta data.
• If not found, component tries to find the service registered using providers meta data.
The hierarchy of the Injector along with work flow of the resolving the service is as follows −
Injectors
NulInjector
Calls
ModuleInjector@platoform Platform
Calls
Calls
ModuleInjector@root Module
Calls Calls
Calls
ElementInjector through providers Component Content child
meta data
Calls
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.
• Template-Driven Approach
• Reactive Approach
Template-Driven Approach
• In this method, the conventional form tag is used to create 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 the case of custom validations, directives can
be used.
• Arguably, this method is the simplest way to create an Angular App.
• 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.
Key differences
The following table summarizes the key differences between reactive and template-driven forms.
REACTIVE TEMPLATE-DRIVEN
Setup of form model Explicit, created in component class Implicit, created by directives
Both reactive and template-driven forms are built on the following base classes.
FormControl Tracks the value and validation status of an individual form control.
FormGroup Tracks the same values and status for a collection of form controls.
FormArray Tracks the same values and status for an array of form controls.
ControlValueAccessor Creates a bridge between Angular FormControl instances and built-in DOM elements.
Form Control
Age
Form Control
Location
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, pristine, valid, invalid, and so on.
Explanation:
As a developer, you would like to know the current value in the text box. You would also be like to know if the value is
valid or not. If the user has changed the value(dirty) or is it unchanged. You would like to be notified when the user
changes its value.
The FormControl is an object that encapsulates all the information related to the single input element. It Tracks the
value and validation status of each of these controls.
The FormControl is just a class. A FormControl is created for each form field. We can refer to them in our component
class and inspect its properties and methods
We can use FormControl to set the value of the Form field. Find the status of form field like (valid/invalid, pristine/dirty,
touched/untouched ), etc. You can add validation rules to it.
Form Group
Age
Form Group
Location
Explanation:
<form>
First Name: <input type="text" name="firstname" />
Last Name: <input type="text" name="lastname" />
Email: <input type="text" name="email" />
</form>
We create a FormControl for each of these input fields. It tracks the value & validity of these elements. All of the above
input fields are represented as the separate FormControl. If we wanted to check the validity of our form, we have to
check the validity of each and every FormControl for validity. Imagine a form having a large no of fields. It is cumbersome
to loop over large no of FormControls and check for validity.
The FormGroup solves this issue by providing a wrapper around a collection of FormControls It encapsulates all the
information related to a group of form elements. It Tracks the value and validation status of each of these controls. We
can use it to check the validity of the elements. set its values & listen for change events, add and run validations on the
group, etc
The FormGroup is just a class. We create a FormGroup to organize and manage the related elements. For Example, form
elements like address, city, state, pin code etc can be grouped together as a single FormGroup. It makes it easier to
manage them. A FormGroup aggregates the values of each child FormControl into one object, with each control name
Reactive Forms
In Reactive Forms approach, it is our responsibility to build the Model using FormGroup, FormControl and FormArray.
To use FormControl, first, we need to import the FormControl from the @angular/forms
Then create the top-level FormGroup. The first argument to FormGroup is the collection of FormControl. They are added
using the FormControl method as shown below.
this.reactiveForm = this.formBuilder.group({
firstname: ['',[Validators.required]],
lastname: [''],
email: [''],
});
Bind the form element with the template using the formControlName directive as shown below
<p>
<label for="firstname">First Name </label>
<input type="text" id="firstname" name="firstname"
formControlName="firstname">
</p>
<p>
<label for="lastname">Last Name </label>
<input type="text" id="lastname" name="lastname" formControlName="lastname">
</p>
<p>
<label for="email">Email </label>
<input type="text" id="email" name="email" formControlName="email">
</p>
<p>
<button type="submit">Submit</button>
</p>
</form>
Template-driven forms
In template-driven forms, the FormControl is defined in the Template. The <Form> directive creates the top-level
FormGroup. We use the ngModel directive on each Form element, which automatically creates the FormControl
instance.
<p>
<label for="firstname">First Name</label>
<input type="text" name="firstname" ngModel>
</p>
<p>
<label for="lastname">Last Name</label>
<input type="text" name="lastname" ngModel>
</p>
<p>
<label for="email">Email </label>
<input type="text" id="email" name="email" ngModel>
</p>
<p>
<button type="submit">Submit</button>
</p>
</form>
Activity Thirteen
They are all properties of the input field, and are either true or false.
They are all properties of the form, and are either true or false.
You can use these states to show meaningful messages to the user. Example, if a field is required, and the user leaves it
blank, you should give the user a warning.
Control Status
The FormGroup tracks the validation status of all the FormControls, which is part of the FormGroup. That also includes
the status of nested FormGroup or FormArray. If any of the control becomes invalid, then the entire FormGroup
becomes invalid.
status
The Angular runs validation checks, whenever the value of a form control changes. Based on the result of the validation,
the FormGroup can have four possible states.
• VALID: All the controls of the FormGroup has passed all validation checks.
• INVALID: At least one of the control has failed at least one validation check.
• PENDING: This Group is in the midst of conducting a validation check.
• DISABLED: This FormGroup is exempt from validation checks
//reactive forms
this.reactiveForm.status
Valid
A FormGroup is valid when it has passed all the validation checks and the FormGroup is not disabled.
invalid
invalid: boolean
A FormGroup is invalid when one of its controls has failed a validation check or the entire FormGroup is disabled.
pending
pending: boolean
A FormGroup is pending when it is in the midst of conducting a validation check.
disabled
disabled: boolean
A FormGroup is disabled when all of its controls are disabled.
enabled
enabled: boolean
A FormGroup is enabled as long one of its control is enabled.
pristine: boolean
A FormGroup is pristine if the user has not yet changed the value in the UI in any of the controls
dirty
dirty: boolean
A FormGroup is dirty if the user has changed the value in the UI in any one of the control.
touched
touched: boolean
True if the FomGroup is marked as touched. A FormGroup is marked as touched once the user has triggered a blur
event on any one of the controls
untouched
untouched: boolean
True if the FormGroup has not been marked as touched. A FormGroup is untouched if the user has not yet triggered a
blur event on any of its child controls.
Built-in Validators
The above creates a form control with a required validator function attached
These required, minlength, maxlength and pattern attributes are already in the official HTML specification. They are a
core part of HTML and we don’t actually need Angular in order to use them. If they are present in a form then the
browser will perform some default validation itself. However, we do need a way for Angular to recognise their presence
and support the same validation logic in our own Angular forms.
If you remember template-driven forms are just model-driven forms but with the creation of the model driven by the
template, they still have an underlying model. Therefore, just like model-driven forms we need to attach a validator
function to the underlying model form control. Angular does this by secretly creating special validator directives which
have selectors matching required, minlength, maxlength and pattern.
So, if you have imported FormsModule into your ngModule then anytime Angular sees a required tag in the HTML it will
link it to an instance of a directive called RequiredValidator. This directive validator applies the same Validators.required
function as we use in model-driven forms. That’s how the built-in validators work.
We can group various FormControls together. For Example, fields such as street, city, country and Pincode each will
have their own FormControl but can be grouped together as an address FormGroup.
In the code above, we have created new FormGroup Address and added three form controls i.e city, street, country &
Pincode.
In the template use the formGroupName directive to enclose the control using a div element as shown below
<div class="form-group">
<label for="city">City</label>
<input type="text" class="form-control" name="city" formControlName="city" >
</div>
<div class="form-group">
<label for="street">Street</label>
<input type="text" class="form-control" name="street"
formControlName="street" >
</div>
<div class="form-group">
<label for="pincode">Pin Code</label>
<input type="text" class="form-control" name="pincode"
formControlName="pincode">
</div>
<p>
<label for="country">country </label>
<select id="country" name="country" formControlName="country">
<option value="1">India</option>
<option value="2">USA</option>
<option value="3">England</option>
<option value="4">Singapore</option>
</select>
</p>
</div>
Output:
The FormBuilder is used to create a big reactive form with minimum code in Angular application. The FormBuilder
methods are group(), control() and array() that returns FormGroup, FormControl and FormArray respectively. Using
FormBuilder we can directly pass object or array of object of a class to create the form. We need to create form HTML
template with formArrayName by assigning the field name of that class.
Suppose we want to create a FormGroup with some fields, then first create a class with those fields and then pass the
instance of that class to FormBuilder.group() and it will return FormGroup with form controls named as class fields. After
form submit, we can get complete form value as an object of a class. In this way, with the help of FormBuilder, we can
create form using object of a class, set values in the form using object of a class and also we can fetch form values as an
object of a class after form submit. Now we will provide complete FormBuilder example step-by-step.
FormBuilder creates reactive form with minimum code using FormGroup, FormControl and FormArray. FormBuilder has
following methods.
this.teamForm = this.formBuilder.group({
teamName: ['', Validators.required ],
teamManager: '',
teamDept: this.formBuilder.group(new Department()),
employees: this.formBuilder.array([])
});
Form Validation
Angular offers client-side form validation. Angular monitors the state of the form and input fields (input, textarea,
select), and lets you notify the user about the current state. Angular also holds information about whether they have
been touched, or modified, or not.
You can use standard HTML5 attributes to validate input, or you can make your own validation functions.
To add validation to a template-driven form, you add the same validation attributes as you would with native HTML
form validation. Angular uses directives to match these attributes with validator functions in the framework.
Every time the value of a form control changes, Angular runs validation and generates either a list of validation errors
that results in an INVALID status, or null, which results in a VALID status.
You can then inspect the control's state by exporting ngModel to a local template variable. The following example
exports NgModel into a variable called name:
</div>
• The <input> element carries the HTML validation attributes: required and minlength. It also carries a custom
validator directive, forbiddenName. For more information, see the Custom validators section.
• #name="ngModel" exports NgModel into a local variable called name. NgModel mirrors many of the properties
of its underlying FormControl instance, so you can use this in the template to check for control states such as
valid and dirty. For a full list of control properties, see the AbstractControl API reference.
o The *ngIf on the <div> element reveals a set of nested message dives but only if the name is invalid and the
control is either dirty or touched.
o Each nested <div> can present a custom message for one of the possible validation errors. There are
messages for required, minlength, and forbiddenName.
In a reactive form, the source of truth is the component class. Instead of adding validators through attributes in the
template, you add validator functions directly to the form control model in the component class. Angular then calls
these functions whenever the value of the control changes.
Validator functions
Sync validators Synchronous functions that take a control instance and immediately return either a set of
validation errors or null. Pass these in as the second argument when you instantiate
a FormControl.
Async validators Asynchronous functions that take a control instance and return a Promise or Observable that
later emits a set of validation errors or null. Pass these in as the third argument when you
instantiate a FormControl.
For performance reasons, Angular only runs async validators if all sync validators pass. Each must complete before errors
are set.
You can choose to write your own validator functions, or you can use some of Angular's built-in validators.
The same built-in validators that are available as attributes in template-driven forms, such as required and minlength,
are all available to use as functions from the Validators class. For a full list of built-in validators, see the following link-
https://angular.io/api/forms/Validators
@NgModule({
imports: [BrowserModule, ReactiveFormsModule],
...
})
export class AppModule {}
Step 2: And can then build our form either using FormControl and FormGroup APIs:
In this example, the name control sets up two built-in validators —Validators.required and Validators.minLength(4)—
and one custom validator, forbiddenNameValidator.
All of these validators are synchronous, so they are passed as the second argument. Notice that you can support multiple
validators by passing the functions in as an array.
This example also adds a few getter methods. In a reactive form, you can always access any form control through the
get method on its parent group, but sometimes it's useful to define getters as shorthand for the template.
If you look at the template for the name input again, it is fairly similar to the template-driven example.
<div *ngIf="name.errors?.['required']">
Name is required.
</div>
<div *ngIf="name.errors?.['minlength']">
Name must be at least 4 characters long.
</div>
<div *ngIf="name.errors?.['forbiddenName']">
Name cannot be Bob.
</div>
</div>
This form differs from the template-driven version in that it no longer exports any directives. Instead, it uses the name
getter defined in the component class.
Notice that the required attribute is still present in the template. Although it's not necessary for validation, it should be
retained to for accessibility purposes.
The built-in validators don't always match the exact use case of your application, so you sometimes need to create a
custom validator.
Consider the forbiddenNameValidator function from previous reactive-form examples. Here's what the definition of
that function looks like.
shared/forbidden-name.directive.ts (forbiddenNameValidator)
In this sample, the forbidden name is "bob", so the validator rejects any hero name containing "bob". Elsewhere it could
reject "alice" or any name that the configuring regular expression matches.
The forbiddenNameValidator factory returns the configured validator function. That function takes an Angular control
object and returns either null if the control value is valid or a validation error object. The validation error object typically
has a property whose name is the validation key, 'forbiddenName', and whose value is an arbitrary dictionary of values
that you could insert into an error message, {name}.
Custom async validators are similar to sync validators, but they must instead return a Promise or observable that later
emits null or a validation error object. In the case of an observable, the observable must complete, at which point the
form uses the last value emitted for validation.
In reactive forms, add a custom validator by passing the function directly to the FormControl
• In template-driven forms, add a directive to the template, where the directive wraps the validator function. For
example, the corresponding ForbiddenValidatorDirective serves as a wrapper around the
forbiddenNameValidator.
forbidden-name.directive.ts (providers)
forbidden-name.directive.ts (directive)
@Directive({
selector: '[appForbiddenName]',
providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective,
multi: true}]
})
export class ForbiddenValidatorDirective implements Validator {
@Input('appForbiddenName') forbiddenName = '';
template/hero-form-template.component.html (forbidden-name-input)
Activity Fifteen
Let’s say we want to implement a simple quiz where you need to guess the right colors of the flag of a country.
Yes, it’s France. The flag of France is blue, white, and red ?. We can now use custom validators to validate that the first
input field must be blue, the second one white, and the third one red.
Let’s go ahead and implement some custom Validators. Let’s start with the Validator that validates that we entered blue
as a color.
The validator itself is just a function that accepts an AbstractControl and returns an Object containing the validation
error or null if everything is valid. Once the blue validator is finished, we can import it in our Component and use it.
ngOnInit(){
this.flagQuiz = fb.group({
firstColor: new FormControl('', blue()),
secondColor: new FormControl(''),
thirdColor: new FormControl('')
}, {updateOn: 'blur'});
}
The firstColor input field is now validated. If it doesn’t contain the value blue our validator will return an error object
with the key wrongColor and the value we entered. We can then add the following lines in our HTML to print out a sweet
error message.
<div *ngIf="flagQuiz.get('firstColor').errors?.wrongColor"
class="invalid-feedback">
Sorry, {{flagQuiz.get('firstColor')?.errors?.wrongColor}} is wrong
</div>
To make our custom validator accessible for template-driven forms, we need to implement our validator as a directive
and provide it as NG_VALIDATORS.
@Directive({
selector: '[blue]',
providers: [{
provide: NG_VALIDATORS,
useExisting: BlueValidatorDirective,
multi: true
}]
})
export class BlueValidatorDirective implements Validator {
Note the similarity of the signature of our validate function and the validate method we implemented here. They are
the same. Both accept an AbstractControl and return either an error object or null.
Of course, it doesn’t make sense to duplicate the validation logic. Therefore, we are going to reuse our validation
function in the validate function of our Directive.
import {
AbstractControl,
NG_VALIDATORS,
Validator,
ValidatorFn
} from '@angular/forms';
import {Directive} from '@angular/core';
@Directive({
selector: '[blue]',
providers: [{
provide: NG_VALIDATORS,
useExisting: BlueValidatorDirective,
multi: true
}]
})
export class BlueValidatorDirective implements Validator {
In our app.module.ts we can now add our Directive to the declarations and start to use it in our templates.
We created a custom validator that is usable within reactive forms and template-driven forms. With the same approach,
we could now also implement a validator for the other colors white and red.
Example 2:
Template driven forms is created using directives in the template. It is mainly used for creating a simple form application.
Let’s understand how to create template driven forms in brief.
Configure Forms
Before understanding forms, let us learn how to configure forms in an application. To enable template driven forms,
first we need to import FormsModule in app.module.ts. It is given below −
@NgModule({
declarations: [
AppComponent,
FormcomponentComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule
Once, FormsModule is imported, the application will be ready for form programming.
Let us create a sample application (template-form-app) to learn the template driven form.
Open command prompt and create new Angular application using below command −
cd /go/to/workspace
ng new template-form-app
cd template-form-app
<div class="container">
<h1>User Registration</h1>
<form>
<div class="form-group">
Finally, start your application (if not done already) using the below command –
ng serve
Now, run your application and you could see the below response –
Type the text in the text field and enter submit. The Submit() function will be called and the successful submission of
the form will sent as an argument. The Submit() function will show the text as form submitted in the console as shown
below-−
Reactive Forms is created inside component class so it is also referred as model driven forms. Every form control will
have an object in the component and this provides greater control and flexibility in the form programming. Reactive
Form is based on structured data model. Let’s understand how to use Reactive forms in angular.
To enable reactive forms, first we need to import ReactiveFormsModule in app.module.ts. It is defined below
@NgModule({
declarations: [
AppComponent,
FormcomponentComponent
],
imports: [
BrowserModule,
Open command prompt and create new Angular application using below command −
cd /go/to/workspace
ng new reactive-form-app
cd reactive-form-app
Example:
We are creating a ‘User Registration’ form consisting of four fields, viz, Firstname, Lastname, Email ID, and Password.
Step 1: create a component using the Angular CLI and provide the name of your choice.
@NgModule({
declarations: [
AppComponent,
NewComponentComponent,
FormComponentComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Create a form tag within a div tag to create the four fields.
<div class="container">
<h1>User Registration</h1>
<form>
<div class="form-group">
<label for="firstname">First Name</label><br>
<input type="text" name="firstname" class = "form-control" ngModel>
</div>
<pre></pre>
When you inspect the form, classes like ng-untouched, ng-pristine, and ng-valid are added. This indicates that Angular
has recognized the form tag and has added the classes to the form as well as the fields. By adding the ngModel directive
in the input tag, form controls are added to every input field.
<form (ngSubmit)="submit()">
The submit method can be defined in the component, i.e., form-component.component.ts file.
To generate the JavaScript Representation, another directive called NgForm is assigned to a template variable.
If you observe closely, the value object includes the form controls for the input fields.
One way to ensure that all the fields are filled correctly is by disabling the submit button in case the fields aren’t filled.
Apart from this, you can also specify certain properties in your input tag for the corresponding input field.
Let’s say, that the fields can’t be empty and the form only accepts names with a minimum length of 2 and a maximum
length of 7.
To check this, we’ve submitted the form without filling the FirstName field and evidently, an error can be seen.
To do that, you need to access the form control objects and for that, create a template variable for the field and assign
it to the form control object.
When submitted without filling the FirstName field, the invalid property is set to true.
A component instance has a lifecycle that starts when Angular instantiates the component class and renders the
component view along with its child views. The lifecycle continues with change detection, as Angular checks to see when
data-bound properties change, and updates both the view and the component instance as needed. The lifecycle ends
when Angular destroys the component instance and removes its rendered template from the DOM. Directives have a
similar lifecycle, as Angular creates, updates, and destroys instances in the course of execution.
Your application can use lifecycle hook methods to tap into key events in the lifecycle of a component or directive to
initialize new instances, initiate change detection when needed, respond to updates during change detection, and clean
up before deletion of instances.
Phases
A component in Angular has a life-cycle, a number of different phases it goes through from birth to death.
We can hook into those different phases to get some pretty fine grained control
of our application.
To do this we add some specific methods to our component class which get
called during each of these life-cycle phases, we call those methods hooks.
These phases are broadly split up into phases that are linked to the component
itself and phases that are linked to the children of that component.
• constructor
In the following example, the child component declares the property message as the input property
@Input() message:string
The parent can send the data to the child using the property binding as shown below.
<app-child [message]="message">
</app-child>
The change detector checks if such input properties of a component are changed by the parent component. If it is then
it raises the ngOnChanges hook.
• ngOnInit
o The Angular raises the ngOnInit hook, after it creates the component and updates its input properties. It
raises it after the ngOnChanges hook.
o This hook is fired only once and immediately after its creation (during the first change detection).
These hooks are only called for components and not directives.
• ngAfterContentInit
o ngAfterContentInit Life cycle hook is called after the Component’s projected content has been fully
initialized. Angular also updates the properties decorated with the ContentChild and ContentChildren
before raising this hook. This hook is also raised, even if there is no content to project.
o The content here refers to the external content injected from the parent component via Content Projection.
The Angular Components can include the ng-content element, which acts as a placeholder for the content from the
parent as shown below.
Parent injects the content between the opening & closing element. Angular passes this content to the child component.
<h1>Parent Component</h1>
<app-child> This <b>content</b> is injected from parent</app-child>
During the change detection cycle, Angular checks if the injected content has changed and updates the DOM.
• ngAfterContentChecked
o ngAfterContentChecked Life cycle hook is called during every change detection cycle after Angular finishes
checking of component’s projected content. Angular also updates the properties decorated with the
ContentChild and ContentChildren before raising this hook. Angular calls this hook even if there is no
projected content in the component
o This hook is very similar to the ngAfterContentInit hook. Both are called after the external content is
initialized, checked & updated. Only difference is that ngAfterContentChecked is raised after every change
detection cycle. While ngAfterContentInit during the first change detection cycle.
o This is a component only hook.
• ngAfterViewInit
o ngAfterViewInit hook is called after the Component’s View & all its child views are fully initialized. Angular
also updates the properties decorated with the ViewChild & ViewChildren properties before raising this
hook.
o The View here refers to the template of the current component and all its child components & directives.
o This hook is called during the first change detection cycle, where angular initializes the view for the first
time
o At this point all the lifecycle hook methods & change detection of all child components & directives are
processed & Component is completely ready
o This is a component only hook.
Activity Sixteen
Adding Hooks
In order to demonstrate how the hooks, let’s change the appComponent so it hooks into all the phases.
All we need to do is to add functions to the component class matching the hook names, like so:
app.component.ts
@Component({
selector: "my-app",
changeDetection:ChangeDetectionStrategy.Default,
template: `
<h1>Angular Life Cycle Hooks</h1>
Reference :
<a
href=" https://angular.io/guide/lifecycle-hooks"
>Angular Life Cycle Hooks</a
>
<h1>Root Component</h1>
<br />
<br />
<app-child [message]="message" *ngIf="!hideChild">
<!-- Injected Content -->
<b> {{ content }} </b>
</app-child>
`
})
export class AppComponent {
name = "Angular " + VERSION.major;
message = "Hello";
content = "Hello";
hideChild=false;
constructor() {
console.log("AppComponent:Contructed");
}
ngOnInit() {
console.log("AppComponent:ngOnInit");
}
ngDoCheck() {
console.log("AppComponent:DoCheck");
}
ngAfterContentInit() {
console.log("AppComponent:ngAfterContentInit");
}
ngAfterContentChecked() {
console.log("AppComponent:AfterContentChecked");
}
ngAfterViewInit() {
console.log("AppComponent:AfterViewInit");
}
ngAfterViewChecked() {
console.log("AppComponent:AfterViewChecked");
}
ngOnDestroy() {
console.log("AppComponent:ngOnDestroy");
}
}
• We are listening to all the hooks and logging them to the console.
• There are two form fields message & content. We pass both to the child component. One as input property &
the other via content projection
Child.component.ts
@Component({
selector: 'app-child',
changeDetection:ChangeDetectionStrategy.Default,
template: `
<h2>child component</h2>
<br>
<!-- Data as a input -->
Message from Parent via @input {{message}}
<br><br>
<app-grand-child [customer]="customer"></app-grand-child>
`
})
export class ChildComponent {
@Input() message:string
customer:Customer = new Customer()
constructor() {
console.log(" ChildComponent:Contructed");
}
ngOnChanges() {
console.log(" ChildComponent:ngOnChanges");
}
ngOnInit() {
console.log(" ChildComponent:ngOnInit");
}
ngDoCheck() {
console.log(" ChildComponent:DoCheck");
}
ngAfterContentInit() {
console.log(" ChildComponent:ngAfterContentInit");
}
ngAfterContentChecked() {
console.log(" ChildComponent:AfterContentChecked");
}
ngAfterViewInit() {
console.log(" ChildComponent:AfterViewInit");
}
ngAfterViewChecked() {
console.log(" ChildComponent:AfterViewChecked");
}
ngOnDestroy() {
}
• We are listening to all the hooks
• @Input decorator marks the message as input property. It will receive the data from the parent
• <ng-content></ng-content> is the place holder to receive the projected content from the parent.
• Two forms fields for customer object, which we pass it to the GrandChildComponent
grandchild.component.ts
@Component({
selector: 'app-grand-child',
changeDetection:ChangeDetectionStrategy.Default,
template: `
<h3>grand child component </h3>
<br>
Name {{customer.name}}
`,
})
export class GrandChildComponent {
@Input() customer:Customer
constructor() {
console.log(" GrandChildComponent:Contructed");
}
ngOnChanges() {
console.log(" GrandChildComponent:ngOnChanges");
}
ngOnInit() {
console.log(" GrandChildComponent:ngOnInit");
}
ngDoCheck() {
console.log(" GrandChildComponent:DoCheck");
}
ngAfterContentInit() {
Output:
Components that define a base structure/behaviour but still can be used in various contexts/ dynamic content. Every
time you use a reusable component, you also have a parent component. This flexible content inside the reusable
component comes from parent content and ends up in a dedicated slot inside the reusable component. So it is projected
down to the parent component.
ng-template
Angular ngTemplateOutlet can be used to insert a common template in various sections of a view. A reusable component
where anything from a parent can be inserted into the child view using templateRef. Therefore, you get customized/
modified changes from the parent component & reusable code from the child component.
Example:
@Component({
selector: 'app-root',
data = [{
name : 'Sam Johnson',
dept : 'Electrical'
},{
name : 'Roy Thomas',
dept : 'Mechanical'
},{
name : 'Jim Lasker',
dept : 'Medical'
}]
}
To make the application appealing, let's add bootstrap to the Angular project. From the Angular CLI execute the
following command:
Now add the Bootstrap scripts and CSS files to the angular.json file.
"styles": [
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/popper.js/dist/umd/popper.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js"
]
Let's render a list of the data you defined in app.component.ts file. Add the following HTML code to the
app.component.html file.
Save the above changes and you'll be able to see the list of employees based on the data in the app.component.ts file.
You just added some code to render a list of items. As you can see in the list presented above, the total count is presented
next to each item. There might be scenarios where you might not be needing the count but rather the same list. So the
same code works for you with a bit of modification.
Let's make the list rendering code reusable by creating a separate component altogether. The item count can be made
configurable to display or hide as per need.
Move the app.component.html and the app.component.css code to data-list.component.html and data-
list.component.css respectively.
For the time being, let's also move the data to data-list.component.ts. Eventually, you'll be passing the data to the
component using @Input decorator.
data = [{
name : 'Sam Johnson',
dept : 'Electrical'
},{
name : 'Roy Thomas',
dept : 'Mechanical'
},{
name : 'Jim Lasker',
dept : 'Medical'
}];
constructor() { }
ngOnInit(): void {
}
}
Save the changes and reload your Angular application. You won't be able to see the data list rendered.
You created an Angular component to render the list. But for it to render you need to use the DataListComponent
selector app-data-list in the app.component.html.
<app-data-list></app-data-list>
Save the changes and you'll be able to see the data list.
A common pattern in Angular is sharing data between a parent component and one or more child components. You can
implement this pattern by using the @[Input]() and @[Output]() directives.
Let's start by defining the @Input decorator inside the DataList component.
@Component({
selector: 'app-data-list',
templateUrl: './data-list.component.html',
styleUrls: ['./data-list.component.css']
})
export class DataListComponent implements OnInit {
@Input() data;
@Input() showCount = false;
constructor() { }
ngOnInit(): void {
}
}
As seen in the above code, you have defined two @Input decorators, one for passing the data to render and another, a
Boolean, to decide whether to show count info.
In the data-list.component.html modify the HTML to configure the data as per the @Input parameters.
Modify the app.component.html file to pass the @Input decorators to the reusable child component.
<app-data-list [data]="data2"></app-data-list>
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'angular-pro';
data1 = [{
name : 'Sam Johnson',
dept : 'Electrical'
},{
name : 'Roy Thomas',
dept : 'Mechanical'
},{
name : 'Jim Lasker',
dept : 'Medical'
}];
data2 = [{
name : 'Johnson',
dept : 'Physics'
},{
Save the above changes and you will be able to see two lists of data rendered.
• ng-template has the ability to hold content without rendering it. It is the underlying mechanism to all directives
that modify the DOM structure and therefore a fundamental concept behind all structural Angular directives
like *ngIf or *ngFor.
• ng-template is very powerful and can be used for multiple things, one of them is creating flexible components
by passing a template to a host component.
Activity Seventeen
Ng-content
First, let's take a look at how we would design the button component without ng-content. We define an input value and
using curly braces to display the text.
about.component.ts
@Component({
selector: 'ng-button',
template: `<button (click)="onButtonClicked()">{{text}} </button>
`
})
export class AboutComponent implements OnInit {
@Input()
text!: string;
public onButtonClicked(){
ngOnInit(): void {
}
app.component.html
When using curly braces, the text of the button is coming from the component itself. While this solution does the job,
there is a better one out there: <ng-content></ng-content>
• Using <ng-content>
Instead of using curly braces and keeping track of the input value, we can pass the value into the component from its
execution context using <ng-content>.
about.component.ts
@Component({
selector: 'ng-button',
template: `<button (click)="onButtonClicked">
<ng-content></ng-content>
</button>
`
})
export class AboutComponent implements OnInit {
@Input()
text!: string;
ngOnInit(): void {
}
}
ng-content is similar to ng-transclude in AngularJs. It works as a placeholder. Whatever content is placed between the
button component will be displayed instead of ng-content.
app.component.html
The use of ng-content removes complexity, making the code cleaner and more readable. The good thing is we are not
limited to just one ng-content element.
We can define multiple content slot using <ng-content></ng-content> and the Selector select. Let's create a card
component with a header, content and footer section.
about.component.ts
@Component({
selector: 'ng-button',
template: `
<div class="card">
<header>
<ng-content select="card-header"></ng-content>
</header>
<div class="card-content">
app.component.html
<card>
<card-header> post: ng-content in Angular</card-header>
<card-content>
how does ng-content work...
</card-content>
<card-footer>
<ng-button>edit post</ng-button>
<ng-button>publish post</ng-button>
</card-footer>
</card>
</card>
If we are using the elements which we defined via select, Angular will throw the following error:
Angular Routing
In Angular, routing plays a vital role since it is essentially used to create Single Page Applications. These applications are
loaded just once, and new content is added dynamically. Applications like Google, Facebook, Twitter, and Gmail are a
few examples of SPA. The best advantage of SPA is that they provide an excellent user experience and you don’t have
to wait for pages to load, and by extension, this makes the SPA fast and gives a desktop-like feel.
It generally specifies navigation with a forward slash followed by the path defining the new content.
Angular provides extensive set of navigation feature to accommodate simple scenario to complex scenario. The process
of defining navigation element and the corresponding view is called Routing. Angular provides a separate module,
RouterModule to set up the navigation in the Angular application.
Configure Routing
Angular CLI provides complete support to setup routing during the application creation process as well as during working
an application. Let us create a new application with router enabled using below command –
ng new <name-application>
When you type yes, the app routing file is created along with the application folder.
Angular CLI generate a new module, AppRoutingModule for routing purpose. The generated code is as follows-
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Here,
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Here,
Angular CLI provides option to set routing in the existing application as well. The general command to include routing in
an existing application is as follows –
This will generate new module with routing features enabled. To enable routing feature in the existing module
(AppModule), we need to include extra option as specified below –
Here, module app configures the newly created routing module, AppRoutingModule in the AppModule module.
Here,
Creating routes
Creating a route is simple and easy. The basic information to create a route is given below −
Here,
<router-outlet></router-outlet>
Here,
Sometime, we need to access routing inside the component instead of template. Then, we need to follow below steps:
Here,
this.router.navigate(['about']);
Route path is similar to web page URL and it supports relative path as well. To access AboutComponent from another
component, say HomePageComponent, simple use .. notation as in web url or folder path.
Here,
Route ordering
Route ordering is very important in a route configuration. If same path is configured multiple times, then the first
matched path will get called. If the first match fails due to some reason, then the second match will get called.
Redirect routes
Angular route allows a path to get redirected to another path. redirectTo is the option to set redirection path. The
sample route is as follows −
Here,
redirectTo sets about as the redirection path if the actual path matches empty string.
Wildcard route will match any path. It is created using ** and will be used to handle non existing path in the application.
Placing the wildcard route at the end of the configuration make it called when other path is not matched.
Here,
If a non existent page is called, then the first two route gets failed. But, the final wildcard route will succeed and the
PageNotFoundComponent gets called.
In Angular, we can attach extra information in the path using parameter. The parameter can be accessed in the
component by using paramMap interface. The syntax to create a new parameter in the route is as follows −
Here, we have attached id in the path. id can be accessed in the ItemComponent using two techniques.
• Using Observable.
• Using snapshot (non-observable option).
Using Observable
• has(name) − Returns true if the specified name is available in the path (parameter list).
• get(name) − Returns the value of the specified name in the path (parameter list).
• getAll(name) − Returns the multiple value of the specified name in the path. get() method returns only the first
value when multiple values are available.
• keys − Returns all parameter available in the path.
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.id = params.get('id);
});
}
this.item$ = this.route.paramMap.pipe(
switchMap(params => {
this.selectedId = Number(params.get('id'));
return this.service.getItem(this.selectedId);
})
);
Using snapshot
snapshot is similar to Observable except, it does not support observable and get the parameter value immediately.
let id = this.route.snapshot.paramMap.get('id');
In general, router-outlet will be placed in root component (AppComponent) of the application. But, router-outlet can
be used in any component. When router-outlet is used in a component other then root component, the routes for the
particular component has to be configured as the children of the parent component. This is called Nested routing.
Let us consider a component, say ItemComponent is configured with router-outlet and has two routerLink as specified
below:
<h2>Item Component</h2>
<nav>
<ul>
<li><a routerLink="view">View</a></li>
<li><a routerLink="edit">Edit</a></li>
</ul>
</nav>
<router-outlet></router-outlet>
The route for the ItemComponent has to be configured as Nested routing as specified below:
component: ItemComponent,
children: [
{
path: 'view',
component: ItemViewComponent
},
{
path: 'edit',
component: ItemEditComponent
}
]
}]
Query Parameters
The query parameters feature in Angular lets you pass the optional parameters while navigating from one route to
another. When you pass a query parameter to a specific route, it looks something like this,
As you can see in the above URL, the category is the query parameter and watches is its value.
The Angular router service comes bundled with the navigate method which lets you move from one route to another.
The first argument to this method is an array of URL fragments that represents a route. This method also accepts a
second argument in form of an object. This object could be utilized to specify the query params.
Let's understand this in detail with the help of the URL mentioned in the above section. Let's say that we wish to navigate
to the orders page with category as the query parameter and watches as its value. We can do this using the following
code snippet:
filterWatches() {
this.router.navigate(['/orders'], { queryParams: { category: 'watches' } });
}
As you can see in the above code snippet, the parameters ['/orders'] and { queryParams: { category: 'watches' } } passed
to the navigate method lets Angular know that it needs to navigate to the orders route with category = watches in the
query parameters.
You could also pass multiple parameters by adding multiple key-value pairs to queryParams object.
filterWatches(): void {
this.router.navigate(['/orders'], { queryParams: { category: 'watches', type:
'analog' } });
}
The above code will pass two query parameters, category and type to the orders route and the URL will look like this,
http://localhost:4200/orders?category=watches&type=analog
In our first example, when we moved to orders it sends a query parameter category to the route. However, this
parameter is lost when we try to navigate away from this page.
However, if we wish to preserve; i.e. persist the query params we could do that by adding queryParamsHandling option
to navigate the method of the next route.
home(): void {
this.router.navigate(['/home'], { queryParamsHandling: 'preserve' });
}
http://localhost:4200/home?category=watches
If the home route has its own query parameter then we could use merge instead of preserve.
home() {
this.router.navigate(['/home'], { queryParams: { message: 'hello' },
queryParamsHandling: 'merge' });
}
http://localhost:4200/home?category=watches&message=hello
You could also use queryParams directive to pass the query parameters, instead of Router service.
You could also use queryParamsHandling directive to specify the preserve or merge option.
In order to access the parameters, we need to utilize the ActivatedRoute service. The ActivatedRoute service consists of
queryParams property which holds an observable. Subscribing to this observable will give you access to query
parameters passed in the URL. Let's understand this using the orders route example,
The first thing we need to do is to inject the ActivatedRoute route inside the component where we wish to access the
parameters.
@Component({...})
export class OrdersComponent implements OnInit {
constructor(private route: ActivatedRoute) { }
ngOnInit(): void {
...
}
}
ngOnInit(): void {
this.route.queryParamMap.subscribe(params => console.log(params)); // output:
}
http://localhost:4200/orders?category=watches
For the above URL output in the console will look something like this,
Most front-end applications need to communicate with a server over the HTTP protocol, to download or upload data
and access other back-end services. Angular provides a client HTTP API for Angular applications, the HttpClient service
class in @angular/common/http.
Perquisites
Before working with the HttpClientModule, you should have a basic understanding of the following:
• TypeScript programming
• Usage of the HTTP protocol
• Angular app-design fundamentals, as described in Angular Concepts
• Observable techniques and operators. See the Observables guide.
app/app.module.ts
@NgModule({
imports: [
BrowserModule,
// import HttpClientModule after BrowserModule.
HttpClientModule,
],
declarations: [
AppComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule {}
You can then inject the HttpClient service as a dependency of an application class, as shown in the following
ConfigService example.
app/config/config.service.ts
@Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
}
The HttpClient service makes use of observables for all transactions. You must import the RxJS observable and operator
symbols that appear in the example snippets. These ConfigService imports are typical.
app/config/config.service.ts
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
Note:
• Use the options object to configure various other aspects of an outgoing request. In Adding
headers, for example, the service set the default headers using the headers option property.
• Use the params property to configure a request with HTTP URL parameters, and
the reportProgress option to listen for progress events when transferring large amounts of
data.
Applications often request JSON data from a server. In the ConfigService example, the app needs a configuration file on
the server, config.json, that specifies resource URLs.
assets/config.json
{
"heroesUrl": "api/heroes",
"textfile": "assets/textfile.txt",
"date": "2020-01-29"
}
To fetch this kind of data, the get() call needs the following options: {observe: 'body', responseType: 'json'}. These are
the default values for those options, so the following examples do not pass the options object. Later sections show some
of the additional option possibilities.
The example conforms to the best practices for creating scalable solutions by defining a re-usable injectable service to
perform the data-handling functionality. In addition to fetching data, the service can post-process the data, add error
handling, and add retry logic.
The ConfigService fetches this file using the HttpClient.get() method.
configUrl = 'assets/config.json';
getConfig() {
return this.http.get<Config>(this.configUrl);
}
The ConfigComponent injects the ConfigService and calls the getConfig service method.
Because the service method returns an Observable of configuration data, the component subscribes to the method's
return value. The subscription callback performs minimal post-processing. It copies the data fields into the component's
config object, which is data-bound in the component template for display.
app/config/config.component.ts
showConfig() {
this.configService.getConfig()
.subscribe((data: Config) => this.config = {
heroesUrl: data.heroesUrl,
textfile: data.textfile,
date: data.date,
});
}
As for any of the HTTP methods that return an observable, the caller, HeroesComponent.update() must subscribe() to
the observable returned from the HttpClient.put() in order to initiate the request.
HttpClient captures both kinds of errors in its HttpErrorResponse. Inspect that response to identify the error's cause.
The following example defines an error handler in the previously defined ConfigService.
app/config/config.service.ts
private handleError(error: HttpErrorResponse) {
if (error.status === 0) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong.
console.error(
`Backend returned code ${error.status}, body was: `, error.error);
}
// Return an observable with a user-facing error message.
return throwError(() => new Error('Something bad happened; please try
again later.'));
}
The handler returns an RxJS ErrorObservable with a user-friendly error message. The following code updates the
getConfig() method, using a pipe to send all observables returned by the HttpClient.get() call to the error handler.
App/config/config.service.ts
The following example shows how to pipe a failed request to the retry() operator before passing it to the error handler.
app/config/config.service.ts
getConfig() {
return this.http.get<Config>(this.configUrl)
.pipe(
retry(3), // retry a failed request up to 3 times
catchError(this.handleError) // then handle the error
);
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
promiseTemp: Promise<boolean>;
createPromise() {
this.promiseTemp = this.testPromise(0);
}
observableTemp: Observable<boolean>;
createObservable() {
this.observableTemp = this.testObservable(0);
}
subscribeObservable() {
this.observableTemp
.subscribe(
result => {
console.log(`Observable Ok: ${result}`);
},
err => {
console.error(err);
});
}
setTimeout(() => {
observer.next(result);
observer.complete();
}, 5000);
})
.catch(err => {
observer.error(err)
});
});
}
HTML code:
<h2>Example of Promise and Observable </h2>
<br/>
<button (click)="createPromise()">Create Promise</button>
<br/>
<br/>
<button (click)="createObservable()">Create Observable</button>
<br/>
<br/>
<button (click)="subscribeObservable()">Subscribe Observable</button>
<br/>
<br/>
<button (click)="createObservableNext()">Create Observable Next</button>
<br/>
<br/>
<button (click)="createToPromiseByObservable()">Create Promise by
Observable</button>
<br/>
Promises are used in Angular to resolve asynchronous operations, and Observables are used when the data comes from
an external source like an API.
Promises can be resolved with a single value or an array of values, and Observables emit one or more values over time.
So, while managing an HTTP search, Promise can only handle a single response for the same request; however, if there
are numerous results to the same request, we must use Observable.
Authentication and authorization are important pieces on almost every serious application. Single Page Applications
(SPAs) are no exception. The application may not expose all of its data and functionality to just any user. Users may have
to authenticate themselves to see certain portions of the application, or to perform certain action on the application.
To identify the user in the application, we need get the user logged in.
There is a difference in the way user management is implemented in traditional server-driven applications and Single
Page Applications. The only way in which SPA can interact with its server components is through AJAX. This is true even
for logging in and logging out.
The server responsible for identifying the user has to expose an authentication endpoint. The SPA will send the
credentials entered by the user to this endpoint to for verification. In a typical token-based authentication system, the
service may respond with an access token or with an object containing the name and role of the logged in user after
validating the credentials. The client has to use this access token in all secured API requests made to the server.
As the access token will be used multiple times, it is better to store it on the client side. In Angular, we can store the
value in a service or a value as they are singleton objects on the client side. But, if the user refreshes the page, the value
in the service or value would be lost. In such case, it is better to store the token using one of the persistence mechanisms
offered by the browser; preferably sessionStorage, as it is cleared once the browser is closed.
Implementing Login
Let’s have a look at some code now. Assume that we have all server side logic implemented and the service exposes a
REST endpoint at /api/login to check login credentials and return an access token. Let’s write a simple service that
performs the login action by hitting the authentication endpoint. We will add more functionality to this service later:
$http.post("/api/login", {
userName: userName,
password: password
}).then(function(result) {
userInfo = {
accessToken: result.data.access_token,
userName: result.data.userName
};
$window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
deferred.resolve(userInfo);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
}
return {
login: login
};
});
• JWT Module
Company Confidential
• CanActivate interface
a. <h6> c. <h1>
b. <heading> d. <head>
a. / c. *
b. ^ d. <
Nothing has been output by the Browser, as we have used comments to explain the structure and have not yet added
any “real” content.