Angular JS framework

In depth overview of angular 2 architecture and features

Angular 1 was based on the MVC architecture whereas Angular 2 is based on a components-and-services architecture. Angular 1 and Angular 2 are completely different in terms of architecture and APIs, so previous knowledge of Angular 1 is unlikely to help you much in learning Angular 2. In this article, we will learn Angular 2 without comparing it with Angular 1 as doing that will create confusion and is unnecessary. Even if you don’t have knowledge about Angular 1, you can continue with this article.

We will cover the following topics:

  1. Web components
  2. The Angular 2 architecture
  3. Template language
  4. Component inputs and outputs
  5. The component life cycle
  6. Events
  7. Forms
  8. Services
  9. More…

The Angular 2 architecture

Angular 2 is a framework for building the client side of web applications, based on a services-and-components architecture.

An Angular 2 application is composed of a view and various services. Services are simple JavaScript objects that hold application logic and state. Services should be reusable. Views consume services, and services can also interact with each other.
Views and services are loosely coupled so that an Angular 2 view can be used with any other architecture, such as Flux. Similarly, services can be used with any other view, such as React.
Angular 2 views are based on component-oriented architecture. In component- oriented architecture, the application UI is divided into reusable components. A component has a UI with code to update the UI and handle user actions on the UI. A custom tag is associated with a component, and whenever the custom tag appears, a new instance of the component is created and rendered. So, we can say that component-oriented architecture is architecture for the view of an application. Actually, the components consume the services.

Here is a diagram from the official Angular 2 website (https://angular.io) that shows the complete architecture of Angular 2:

angular 2 overview

 

Here, you can see that the UI of a Component is defined using a Template. Templates are written using template HTML, that is, a combination of HTML and many other tokens. A component also holds the UI state and event handlers of  the UI.
We shouldn’t store application logic and state inside a component, as it will have   an impact on code reusability and cause issues while developing large and complex apps. Application state and logic should be stored in services.
Angular 2 only implements one-way data binding. This makes large and complex apps easier to debug. Services are injected into specific components that need them, and not all
the components.

Introducing web components

Before we get into web components, you need to know why we are learning about them. Well, we are learning about web components because Angular 2 components utilize shadow DOM and templates, which are a part of web components.
In a nutshell, web components are a collection of four different browser specifications that enable the creation of reusable components in web pages. These four specifications are HTML imports, shadow DOM, templates, and custom elements. They can be used together or separately.
Web components provide native implementation of component-oriented architecture. A component created using web components is called a web component as well.
Before we learn about web components, let’s consider a project for demonstration purposes. Create a directory named web-components, and then create a file named index.html in it. Web components have pretty poor browser support, so let’s download webcomponents.js polyfill. Download the webcomponents.js file from https://github.com/webcomponents/webcomponentsjs and place it in the web-components directory.
Now, place this code in the index.html file:
<!doctype html>
<html>
<head>
<title>Web Components Demo</title>
<script src=”webcomponents.js”></script>
</head>
<body>
<script>
//place JavaScript code here
</script>
</body>
</html>

 

Let’s now look at an overview of shadow DOM, templates, and custom elements by building a component to display a card that has an image, title, and description.

Templates

Templates are used to define reusable code. A template is defined using the
<template> tag. Code for the template is placed inside this tag. We can place any tag, such as <script> and <style>.
The code inside the <template> tag is only parsed, not rendered.
Here is an example of how to create a template. Place this code in the body tag:
<template id=”cardTemplate”>
<style type=”text/css”>
.container
{
width: 250px; float: left;
margin-right: 10px;
}

img
{
width: 100%;
}
</style>
<div class=”container”>
<img src=”” />
<div>
<h3></h3>
<p></p>
</div>
</div>
</template>
Here, the template holds the UI code for the card component. Now, if you open the index.html file in a browser, you won’t see anything because the <template> tag is only parsed, not rendered.

Custom elements

Custom elements let us define new types of HTML elements (that is, new types
of HTML tags). When we use a tag name that’s not recognized by the browser, the browser simply treats it like a <span> tag. But when we register a custom tag, it gets recognized by the browser. It can inherit other elements, lets us perform different operations on different stages of the element lifecycle, and much more.
Let’s create a custom element for our component. Wherever the tag appears, a new instance of the component will be displayed.
Here is the code to display the custom element. Place it in the <body> tag:
<custom-card data-img=”http://placehold.it/250×250″ data- title=”Title 1″ data-description=”Description 1″ is=”custom- card”></custom-card>
<custom-card data-img=”http://placehold.it/250×250″ data- title=”Title 2″ data-description=”Description 2″></custom- card>
We have to use the – character in the custom element name. This is compulsory because this restriction allows the parser to distinguish custom elements from regular elements and ensures forward compatibility when new tags are added to HTML. Here, we are passing properties of the component as data attributes.
Now, let’s define <custom-card> as a custom element and place the template code inside the tag whenever a new instance of <custom-card> is created. To do that, place this code in the <script> tag:
var customCardProto = Object.create(HTMLElement.prototype); customCardProto.createdCallback = function(){
var template = document.querySelector(“#cardTemplate”); template.content.querySelector(“img”).src = this.getAttribute(“data-img”); template.content.querySelector(“h3”).innerHTML = this.getAttribute(“data-title”); template.content.querySelector(“p”).innerHTML = this.getAttribute(“data-description”);

var clone = document.importNode(template.content, true); this.appendChild(clone)
}
var customCard = document.registerElement(“custom-card”, { prototype: customCardProto
});

Here is how the code works:

  1. By default, custom elements inherit methods and properties of HTMLElement.
  2. To register a custom element, we need to use the document. registerElement method. The first argument is the custom tag name and the second argument is an optional object. This optional object can take a property called prototype. The prototype property defines the HTML element it inherits, that is, the properties and methods of the HTML element it inherits. By default, it’s assigned to Object.create(HTMLElement. prototype).
  3. We can also add new properties and methods to our custom element by adding new properties and methods to the object assigned to the prototype property.
  4. Here, we’ve added a method called createdCallback, which is invoked whenever an instance of a custom element is created, that is, either an instance created using JavaScript or HTML.
  5. Inside createdCallback, we are retrieving our template and setting the image source, title, and description and then appending it to the custom element by creating a clone of it, as many custom elements will share the same template.

Now, if you open index.html in a browser, you will see this output:
learn angular js

 

Shadow DOM

Shadow DOM allows HTML elements to get a new kind of node called a shadow root associated with them. An element that has a shadow root associated with it is called a shadow host. The content of a shadow host isn’t rendered; the content of the shadow root is rendered instead. A shadow root can have another shadow root below it.
The benefit of shadow DOM is that CSS styles defined inside a shadow root won’t affect its parent document, and CSS styles defined outside the shadow root will not affect the elements inside the shadow root. This is useful to define styles specific to the components. In short, we can say that shadow DOM provides style encapsulation.
Style encapsulation is not the only benefit of shadow DOM. The HTML inside the shadow root is protected from accidental modification from JavaScript. We can still inspect the shadow root in browser developer tools.
Many native element, such as <video> and <audio>, have a shadow root, but when you inspect it, you won’t see the shadow root. Browsers by default hide the shadow roots of these elements. To see their shadow roots, you need to change browser- specific settings.
Let’s modify the previous custom element code to render the template inside shadow DOM. Replace the previous createdCallback method with this one:
customCardProto.createdCallback = function(){
var template = document.querySelector(“#cardTemplate”); template.content.querySelector(“img”).src = this.getAttribute(“data-img”); template.content.querySelector(“h3”).innerHTML = this.getAttribute(“data-title”); template.content.querySelector(“p”).innerHTML = this.getAttribute(“data-description”);

var clone = document.importNode(template.content, true); var shadow = this.createShadowRoot();
shadow.appendChild(clone);
}
Here, instead of appending the template code directly to the custom element, we created a shadow root using createShadowRoot and appended the template code to it.

Setting up an Angular 2 project

Angular 2 code can be written in JavaScript, TypeScript, or Dart. In case you are writing Angular 2 code in TypeScript or Dart, you will need to transpile the code to JavaScript before serving to the client. We will use JavaScript to write Angular 2 code.
Create a directory named angular2-demo. Then, inside the directory, create the app. js and package.json files. Then, create a directory named public, and inside the directory, create four more directories named html, js, componentTemplates, and componentStyles. Now, create a file named index.html and place it in the html directory.
Then, download angular2-polyfills.js, Rx.umd.js, and angular2-all.umd. js from https://cdnjs.com/libraries/angular.js/ and place them in the angular2-demo/js directory. These files are what they sound like. You can also queue the CDN links directly if you want to.
Inside the index.html file, place this starting code:
<!doctype html>
<html>
<head>
<title>Angular 2 Demo</title>
</head>
<body>

<script src=”/js/angular2-polyfills.js”></script>
<script src=”/js/Rx.umd. js”></script>
<script src=”/js/angular2-all.umdn.js”></script>
<script>
//App code here
</script>
</body>
</html>
Inside the app.js file, place this code:
var express = require(“express”); var app = express();
app.use(express.static( dirname + “/public”)); app.get(“/”, function(httpRequest, httpResponse, next){
httpResponse.sendFile( dirname + “/public/html/index.html”);
})

app.listen(8080);

 

This is the server-side code. It’s self-explanatory.
Now, in the package.json file, place this code and run npm install to download the express package:
{
“name”: “Angular2-Demo”, “dependencies”: {
“express”: “4.13.3”
}
}
To start the server, run node app.js. Then, open the app using localhost:8080 as the address in a browser.

Angular 2 fundamentals

An Angular 2 application is completely split into components. Technically, an Angular 2 component is a reusable custom tag that is mutable and encapsulated with an embedded state, that is, changes to the state or properties will mutate the UI.

All the components of the application are arranged in a tree structure, with a component as the root node.
Here is an example of how to create a component. It creates a card component that displays an image, title, and description. Place this code in the <script> tag:
var Card = ng.core.Component({ selector: “card”,
inputs: [“src”, “title”, “desc”], templateUrl: “templates/card-template.html”, styleUrls: [“templateStyles/card-style.css”]
})
.Class({
constructor: function(){
}
})

 

Then, create a file named card-template.html, and place it in the
componentTemplates directory. Place this code in the file:
<style>
.container
{
width: 250px; float: left;
margin-right: 10px;
}

img
{
width: 100%;
}
</style>
<div class=”container”>
<img src=”{{src}}” />
<div>
<h3>{{title}}</h3>
<p>{{desc}}</p>
</div>
</div>
After that, create a file named card-style.css and place it in the componentStyles
directory. Place this code in the file:
.container
{
width: 250px; float: left;
margin-right: 10px;
}

img
{
width: 100%;
}
This is how these three code snippets work:

  1. A component needs to be created by chaining Component and Class methods that belong to an ng.core object.
  2. The Component method takes a configuration object with various properties, whereas the Class method takes an object with component lifecycle methods, constructors, and UI action handlers.
  3. Here, the configuration properties we’ve provided are selector, inputs, templateUrl, and styleUrls. The selector property is used to define the custom tag for the component. The inputs property is used to define the attributes that the custom tag takes. The templateUrl property is used to define the file containing the template of the component. You can also use template if you want to inline the template code. Finally, styleUrls is used to define the CSS files containing the style for the component. You can also use the styles property to inline CSS code, or you can define CSS using a

<style> tag inside the template itself. CSS defined in any of these three ways won’t affect other components, that is, it’s encapsulated to the component itself.

  1. In the Class method, we will have to provide the constructor method even if it does nothing. It’s invoked during the construction of a new instance of the component. By construction of the component, I mean the construction of the component in memory—not resolving attributes, resolving its  children, rendering its view, and so on. The primary use of the constructor method is to inject services into the component. Services cannot be injected automatically as we may sometimes need to initialize services for every component, and Angular is unaware of how to do this. The constructor method has access to the state of the component but not its properties. Here, we shouldn’t do any heavy work or something else that would slow down

or cause the construction of the component to fail. constructor is not a component lifecycle method.

  1. Then, we have the component template code. In this template file, we are simply rendering the properties passed to the component. To render anything that’s in the component state, we need to use the {{}} token.

 

Let’s create another component called Cards, which displays a list of cards. It gets information about cards from a service.
Place this code in the <script> tag of the index.html file:
var CardsService = ng.core.Class({ constructor: function() {
},
getCards: function() { return [{
src: “http://placehold.it/350×150”, title: “Title 1”,
desc: “Description 1”
},
{
src: “http://placehold.it/350×150”, title: “Title 2”,
desc: “Description 2”
},
{

 

 

 

}
});

 

src: “http://placehold.it/350×150”, title: “Title 3”,
desc: “Description 3”
}]

 

var Cards = ng.core.Component({ selector: “cards”, viewProviders: [CardsService], directives: [Card],
templateUrl: “componentTemplates/cards-template.html”
}).Class({
constructor: [CardsService, function(cardsService){ this.getCards = cardsService.getCards;
}],
ngOnInit: function(){ this.cards = this.getCards();
}
})

var App = ng.core.Component({ selector: “app”, directives: [Cards],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){

}
})

ng.platform.browser.bootstrap(App);
Now, create a file named cards-template.html in the componentTemplates
directory and place this code in it:
<card *ngFor=”#card of cards” title=”{{card.title}}” src=”{{card.src}}” desc=”{{card.desc}}”></card>
Now, create a file named app-template.html in the componentTemplates directory and place this code in it:
<cards></cards>
Now, in the <body> tag of the index.html file, place this code:
<app></app>
Here is how these four code snippets work:

  1. To create a service, we need to use the ng.core.Class method. It takes an object with the constructor method and other methods or properties that the service exposes. While injecting the service into other services or components, a new instance of the service is created and injected. While creating a new instance of a service, the constructor method is called. We have to provide this method even if it doesn’t do anything. The primary purpose of this method is to inject services that this service depends on. Here, our CardsService method is not dependent on any other service, so we have no code inside the constructor method. Then, we defined a getCards

method, which returns data of three different cards to display.

  1. Then, we created a Cards component. It takes the data from CardsService and renders a Card component for each card data. While creating the Cards component, we provide viewProviders and directives properties to the configuration object. viewProviders is the list of services the component

is dependent on, and directives is the list of other components this component renders. Here, you can see that instead of directly assigning a function to the constructor property, we are assigning an array with a list of services the component depends upon and the last array item as the actual function. This is the format of injecting services into components. Inside the constructor method, we store references to the methods or properties of the service that the component needs, that is, we can use services inside the constructor method. We will learn more about viewProviders later on.
The this keyword in any of the methods passed to the Class method points
to the state of the component. After a component instance has been created, whenever the component state changes, the template bindings are updated. We have another method here, called ngOnInit. It’s a lifecycle method that’s invoked after a new instance of the component has been created and its attributes resolved. Inside this, we call the getCards method and store the returned value inside the cards property of the state. Note that the attributes passed to a component tag are accessible using the this keyword after the component instance has been created.

  1. Inside the template of CardsComponent, we are using the *ngFor directive to display the cards. We will learn more about directives later.
  2. Then, we create an App component, which acts as the root of our component. Inside this component, we are displaying the Cards component.
  3. Finally, we initialize the application. An Angular 2 application is initialized explicitly. While initializing it, we need to provide a reference to the root component. This is done to ensure that applications are composed of nested components all the way down. The root component is the one that’s added to the <body> tag. Adding tags of other components to the body tag will not do anything.

Now, if you refresh your localhost:8080 page in your browser, you will see this output:
learn angular js

Styling components and shadow DOM

Earlier, we saw that there are three ways of defining styles specific to components (styles encapsulated in the component template scope). A component’s CSS doesn’t even affect the components it owns.
Angular 2 doesn’t use shadow DOM by default; instead, it uses a different technique to achieve style encapsulation. This is due to the lack of browser support.
By default, Angular 2 modifies the CSS selector in such a way that it only targets the elements in the component, and it then places the CSS in the <head> tag of the page. If you inspect our current app using browser developer tools, you will see this:
learn angular js

Here, you can see that the CSS has been modified and inserted into the <head> tag. To force Angular 2 to use shadow DOM, we need to assign the encapsulation property of the component configuration object to ng.core.ViewEncapsulation. Native. By default, it’s assigned to ng.core.ViewEncapsulation.Emulated.
When you inspect the app after assigning the encapsulation property of the Card and Cards components to ng.core.ViewEncapsulation.Native, you will see something like this:
learn angular js
Here, you can see that shadow DOM was used to achieve style encapsulation.

Angular 2 change detection

Change detection is the process of detecting component state change. The state of a component is stored and manipulated using the this keyword. Therefore, there is no direct way for Angular 2 to detect when the state changes. So, Angular 2 uses complex algorithms and third-party libraries to detect state changes.
The first thing Angular 2 does for detecting state changes is that it pretends that all the changes happen asynchronously. Then, it uses the zone.js library to monitor browser events, timers, AJAX requests, WebSockets, and other asynchronous things that are supported by zone.js.
Now, whenever any of these asynchronous activities takes place, it checks everything that could change, including object properties and array elements of the this keyword of all the components from the root node; if any change is detected, then  the template bindings of the component are updated. Angular 2 doesn’t simply re- render the whole component. Instead, it checks for the bindings that have changed and selects and updates them specifically.
Some components can have a lot of state data, and checking the state for every asynchronous operation will unnecessarily impact app performance if their state has not changed. Therefore, Angular 2 provides an option to mark such kinds of components so that it does not check their states unless the component itself tells Angular 2 to check its state during the next detection cycle, that is, when the next asynchronous activity occurs. Let’s look at an example to demonstrate this.
Place this code above the App component code in the <script> tag of the index. html file:
var SampleComponent1 = ng.core.Component({ selector: “sampleone”,
template: “{{value}}”,
viewProviders: [ng.core.ChangeDetectorRef], changeDetection: ng.core.ChangeDetectionStrategy.Detached
}).Class({
constructor: [ng.core.ChangeDetectorRef, function(cd){ this.cd = cd;
}],
ngOnInit: function(){ this.value = 1; setInterval(function(){
this.value++; this.cd.markForCheck();
}.bind(this), 2000)
}
})
Then, add SampleComponent1 to the directives array of the App component. So now, the App component’s code should be this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){
}
})
Now, add this code to the end of the app-template.html file:
<br style=”clear: both”>
<sampleone></sampleone>
Here is how these three code snippets work:

  • In this example, we are displaying a value that gets incremented every 2 seconds and the template is re-rendered to display the updated value.
  • At first, we create a component called SampleComponent1. It simply displays value. We have set the changeDetection property to ng.core. ChangeDetectionStrategy.Detached, which tells Angular 2 to not check its state change. By default, the changeDetection property is assigned to ng.core.ChangeDetectionStrategy.Default, which tells Angular 2 to check its state change during every change-detection cycle. We then inject the ng.core.ChangeDetectorRef service into the component, which provides various APIs related to change detection. And then, in the ngOnInit method, we increment the value of value every 2 seconds, after which we call the markForCheck method of ng.core.ChangeDetectorRef, which tells Angular 2 to check for changes in the state of the component during the next change-detection cycle. markForCheck will make Angular 2 check for a change in state for the next detection cycle only, not for the ones after that.
  • Then, we simply display SampleComponent1 in the App component.

If a component depends only on its inputs and/or UI events or if you want  a component’s state change, check only whether its inputs have changed or events have been fired; then, you can assign changeDetection to ng.core. ChangeDetectionStrategy.OnPush.

 

Understanding view children and content children

Elements present inside the tags of a component are called content children, and elements present inside the template of a component are called view children.
To display the content children of a component in the component’s view, we need to use the <ng-content> tag. Let’s look at an example of this.
Place this code above the App component’s code:
var ListItem = ng.core.Component({ selector: “item”,
inputs: [“title”],
template: “<li>{{title}} | <ng-content></ng-content></li>”,
}).Class({
constructor: function(){}
})

var List = ng.core.Component({ selector: “list”,
template: “<ul><ng-content select=’item’></ng-content></ul>”
}).Class({
constructor: function(){}
})
Now, change the App component’s code to this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem], templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
To the end of the app-template.html file, add this code:
<br>
<list>
<item title=”first”>first</item>
<item title=”second”>second</item>
</list>
The output of this code is as follows:
JS angular web development

This is how these three code snippets work:

  • In the App component’s template file, we add a <list> tag, which displays a list. And inside its opening and closing tags, we define the individual list items that it should display.
  • We create ListItem and List components that are bound to <list> and

<item> tags, respectively.

  • We add List component to the directives property of the App component, not List, because the <list> tag is present in the template of the App component, and the App component is responsible for creating its instances.
  • The App component looks for the <ng-content> tag in the template of the

List component and renders the List component instances there.

  • <ng-content> takes an optional select attribute that’s assigned to a CSS selector that indicates which elements of the content children we want to display. There can be multiple <ng-content> tags in a template. If the select attribute has not been provided, then all the content children will be rendered. Here, the select attribute is not required; we are using it just for demonstration.

Getting the reference of components of content children and view children

To get access to the reference of components of view children or content children, we can use the ng.core.ContentChildren, ng.coreViewChildren, ng.core.ContentChild, and ng.core.ViewChild constructors. The difference between ng.core.ContentChildren and ng.core.ContentChild is that the first one returns all the references of a given component whereas the second one returns the reference of the first occurrence. The same difference also stands for ng.core.ViewChild and ng.core.ViewChildren.
Here is an example to demonstrate ng.core.ContentChildren. Replace the code for the List component with this:
var List = ng.core.Component({ selector: “list”,
template: “<ul><ng-content select=’item’></ng-content></ul>”, queries: {
list_items: new ng.core.ContentChildren(ListItem)
}
}).Class({
constructor: function(){}, ngAfterContentInit: function(){
this.list_items._results.forEach(function(e){ console.log(e.title);
})
}
})
The output of this code in the console is as follows:
first
second

Most of this code is self-explanatory. What’s new is the ngAfterContentInit lifecycle method. It’s triggered after the content children have been initialized. Similarly, if we want to access the view children, we need to use the ngAfterViewInit lifecycle method.
Note that we only have access to the state of the components—nothing else.

Local template variables

We can assign a local template variable to a content child or view child. Local template variables let us get the reference of any element of the content children or view children, that is, component references or HTML element references.
To assign a local template variable to an element of the view children or content children, we need to place #variable_name in the opening tag.
Here is an example to demonstrate how local template variables work. Place this code above the App component:
var SampleComponent2 = ng.core.Component({ selector: “sampletwo”,
template: “<input type=’text’ #input />”, queries: {
input_element: new ng.core.ViewChild(“input”)
}
}).Class({
constructor: function(){}, ngAfterViewInit: function(){
this.input_element.nativeElement.value = “Hi”;
}
})
Change the App component’s code to this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
And then, add this code to the end of the app-template.html file:
<sampletwo></sampletwo>

The output of this code is as follows:
JS angular web development

Here is how these three code snippets work:

  • We create a new component named SampleComponent2, which displays an HTML input text element. We assign the input element to a local template variable named input.
  • Then, we use the ng.core.ViewChild to get a reference to the element. If we pass a string to ng.core.ViewChild, ng.core.ViewChildren, ng.core. ContentChild, and ng.core.ContentChildren, then they will look for the elements with the same local variable name as the string, and if we pass a component, they will look for the component, like we saw before.
  • The reference of the components we get from the local template variable is of the same interface we got before. But for HTML element references, we can access the real DOM of the element by using the nativeElement property.

Component lifecycle methods

When a component tag appears, Angular 2 creates an instance of a component, renders it, checks for changes in attributes, checks for changes in state, and destroys it when it’s no longer needed. These steps together form the lifecycle of a component.
Angular 2 lets us register methods that are called at various stages of the component lifecycle.
Here are the various lifecycle methods provided by Angular 2; lifecycle hooks are explained in the order they occur:

  • ngOnChanges: This is invoked whenever the attributes of a component change. It’s also invoked after the attributes of a component are resolved for the first time after the creation of a new instance of the component. It’s invoked after the state has been changed due to the attributes but before the view is updated. This method receives the current and previous values of the attributes.
  • ngOnInit: This is invoked after the first instance of ngOnChanges. It states that the component has been successfully created and attributes have been read.
  • ngDoCheck: This is called during every change-detection cycle and right after ngOnInit. We can detect and act upon changes that Angular 2 can’t or won’t detect on its own. This is invoked after Angular 2 is done checking state changes for the component and has updated the state if there was any change in the attributes but before the component view is updated. After this call is over, the view is rendered, and while rendering it, ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit, and ngAfterViewChecked

are invoked.

  • ngAfterContentInit: This is invoked after content children have been initialized but not yet rendered, that is, after the ngOnChanges, ngOnInit, ngDoCheck, ngAfterContentInit, and ngAfterContentChecked methods of the content children have been called.
  • ngAfterContentChecked: This is invoked whenever the change-detection cycle checks whether the content children have changed as well as right after ngAfterContentInit. If there is a change, it’s invoked before the views of the content children are updated. Before invoking it, the query results of ng.core.ViewChildren, ng.core.ContentChildren, and so on are updated, that is, it’s invoked after ngAfterContentChecked of the content children has been invoked. After this call, the content children views

are updated.

  • ngAfterViewInit: This is invoked after view children have been initialized but not yet rendered, that is, after the ngOnChanges, ngOnInit, ngDoCheck, ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit, and ngAfterViewChecked methods of the view children have been called.
  • ngAfterViewChecked: This is invoked whenever the change-detection cycle checks whether the view children have changed as well as right after ngAfterViewInit. If there is a change, it’s invoked before the views of the view children are updated but after the ngAfterViewChecked methods of the view children have been invoked.
  • ngOnDestroy: This is invoked before a component is destroyed. The ngOnDestroy method of a component is invoked before the ngOnDestroy methods of its content children and view children.

Writing templates

We need to use template language to write component templates. Template language is composed of HTML along with the {}, [], (), [()], *, |, and # tokens. Let’s see what each of these is used for and how to use them.

 

Rendering a value

To simply render a property of the this keyword, we need to use the {{}} token. Inside these braces, we can simply place the property name.
We can only place expressions inside braces. The expressions we place inside them look like JavaScript. But there are a few JavaScript expressions that we are not allowed to use inside these braces. Here they are:

  • Assignments (=, +=, -=)
  • The new operator
  • Chaining expressions with ; or ,
  • Increment and decrement operators (++ and –)
  • The bitwise operators | and &

Pipes

We can also place pipes in braces. A pipe is a function that accepts an input value and returns a transformed value. A pipe is represented by the | operator. The final result of expressions inside braces can be transformed using pipes. There can be as many pipes in the braces as we want. A pipe can also take parameters.
Angular 2 provides some built-in pipes: date, uppercase, lowercase, currency, and percent. We can also create our own pipes.
Here is an example of using {{}}. Place this code above the App component:
var SampleComponent3 = ng.core.Component({ selector: “samplethree”,
template: “{{info.firstname + info.lastname | uppercase}}”
}).Class({
constructor: function(){ this.info = {
firstname: “firstname”, lastname: ” lastname”
}
}
})

 

Replace the App component code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
And then, place this in the app-template.html file:
<br><br>
<samplethree></samplethree>
The output of the code is as follows:
JS angular web development

 

Handling events

To handle events of elements in a template, we need to use the () operator. Here is an example of how to handle events. Place this code above the App component code:
var SampleComponent4 = ng.core.Component({ selector: “samplefour”,
template: “<input (click)=’clicked($event)’ (mouseover)=’mouseover($event)’ type=’button’
value=’Click Me!!!’ />”
}).Class({
constructor: function(){ this.clicked = function(e){
alert(“Hi from SampleComponent4”);
};

this.mouseover = function(e){ console.log(“Mouse over event”);
}

}
})
Replace the App component code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4], templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
Place this code in app-template.html:
<br><br>
<samplefour></samplefour>
The preceding code is self-explanatory.

Binding state to element attributes

To bind the value of a property of the this keyword to the attribute of an element in a template, we can simply use {{}}, like this, for example:
<component title=”{{title}}”></component>
But if you want to pass an object, this method will not work, as the expression inside the {{}} token is always converted to a string. Therefore, Angular 2 provides the
[] operator, which enables a component to pass an object through attributes to a
component in its template.
Here is an example to demonstrate this. Place this code above the App component code:
var SampleComponent5 = ng.core.Component({ selector: “samplefive”,
inputs: [“info”],
template: “{{info.name}}”
}).Class({
constructor: function(){}
})

var SampleComponent6 = ng.core.Component({ selector: “samplesix”,
directives: [SampleComponent5],
template: “<samplefive [info]=’myInfo’></samplefive>”
}).Class({

constructor: function(){ this.myInfo = {
name: “Name”
}
}
})
Replace the App component’s code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4, SampleComponent6],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
Place this code at the end of the app-template.html file:
<br><br>
<samplesix></samplesix>
The output of this code is as follows:
JS angular web development

Two-way data binding

By default, Angular 2 doesn’t use two-way data binding. It uses unidirectional binding but offers the [()] operator for two-way data binding, if needed.
Here is an example to demonstrate [()]. Place this code above the App
component’s code:
var SampleComponent7 = ng.core.Component({ selector: “sampleseven”,
template: “<input [(ngModel)]=’name’ /><input (click)=’clicked()’ value=’Click here’ type=’submit’ />”
}).Class({
constructor: function(){}, clicked: function(){
alert(this.name);
}
})
Replace the App component code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4, SampleComponent6, SampleComponent7],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
Place this code in the app-template.html file:
<br><br>
<sampleseven></sampleseven>
The output of this code is as follows:
JS angular web development

Here, enter something in the text field and click on the button. You will see an alert box with the text field’s value.
To capture the value of HTML form elements, we need to place ngModel inside the [()] brackets. We can place an attribute name if we are setting up two-way data binding between inputs and outputs. We will learn more about outputs later.

Directives

Directives are used to change the DOM based on the state. There are two types of directives: attribute directives and structural directives. Let’s look at each of them.

Attribute directives

An attribute directive changes the appearance or behavior of a DOM element based on a change in state. ngClass and ngStyle are the built-in attribute directives.
We can also create our own attribute directives.
The ngClass directive is used to add or remove CSS classes from an element whereas the ngStyle directive is used to set inline styles.
Here is an example of how to use the ngClass and ngStyle directives. Place this code above the App component’s code:
var SampleComponent8 = ng.core.Component({ selector: “sampleeight”,
template: “<div [ngStyle]=’styles’ [ngClass]=’classes’></div>”
}).Class({
constructor: function(){ this.styles = {
“font-size”: “20px”, “font-weight”: “bold”
}

this.classes = { a: true,
b: true, c: false
};
}
})

Replace the App component’s code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4, SampleComponent6, SampleComponent7, SampleComponent8], templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
And then, place this code at the end of the app-template.html file:
<sampleeight></sampleeight>
Now, if you inspect the <sampleeight> tag in browser developer tools, you will see this:
JS angular web development

Most of this code is self-explanatory. You can see that the same [] token is also used for attribute directives. When the [] token is used, Angular 2 first checks to see whether a built-in attribute directive or custom directive is present with that name, and if not, it treats it as an attribute.

Structural directives

A structural directive changes the DOM layout by adding or removing DOM elements. ngIf, ngSwitch, and ngFor are the three built-in structural directives. We can also create our own custom structural directives.
Here is an example to demonstrate ngIf and ngSwitch. We have already seen an example of ngFor previously. Place this code above the App component’s code:
var SampleComponent9 = ng.core.Component({ selector: “samplenine”,
templateUrl: “componentTemplates/samplecomponent9-template.html”
}).Class({
constructor: function(){

this.display1 = true; this.display2 = false; this.switchOption = ‘A’;
}
})
Create a file named samplecomponent9-template.html, and place it in the
componentTemplates directory. Place this code in that file:
<br><br>

<div *ngIf=”display1″>Hello</div>
<div *ngIf=”display2″>Hi</div>

<span [ngSwitch]=”switchOption”>
<span *ngSwitchWhen=”‘A'”>A</span>
<span *ngSwitchWhen=”‘B'”>B</span>
<span *ngSwitchWhen=”‘C'”>C</span>
<span *ngSwitchWhen=”‘D'”>D</span>
<span *ngSwitchDefault>other</span>
</span>
Replace the App component’s code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4, SampleComponent6, SampleComponent7, SampleComponent8, SampleComponent9],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
Finally, place this code in the app-template.html file:
<samplenine></samplenine>
The output of this code is as follows:
JS angular web development

 

Most of this code is self-explanatory. You can see that we are using the * token for structural directives. The * token treats the element as a template, that is, it doesn’t render the element but uses it as a template to create the DOM.
Actually, both attribute and structural directives are written using the [] token, but writing code using structural directives with the [] token makes the code longer.
Therefore, Angular 2 introduced the * token, which makes it easy to write code using structural directives. Internally, Angular 2 translates the code that uses the * token to use the [] token. Learn more about it here:
https://angular.io/docs/ts/latest/guide/template-syntax.html#!#star- template

Outputs

Outputs allow components to emit custom events. For example, if we have a component that displays a button and we want the parent component to be able to add an event handler for the click event of the child component, we can achieve this using outputs.
Here is an example of how to integrate outputs. Place this code above the App
component’s code:
var SampleComponent10 = ng.core.Component({ selector: “sampleten”,
outputs: [“click”], template: “”
}).Class({
constructor: function(){
this.click = new ng.core.EventEmitter(); setInterval(function(){
this.click.next({});
}.bind(this), 10000)
}
})

var SampleComponent11 = ng.core.Component({ selector: “sampleeleven”,
directives: [SampleComponent10], template: “<br><sampleten
(click)=’clicked($event)’></sampleten>{{value}}”
}).Class({
constructor: function(){ this.value = 1;
this.clicked = function(e){ this.value++;
}
}
})
Replace the App component’s code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4, SampleComponent6, SampleComponent7, SampleComponent8, SampleComponent9, SampleComponent11],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
Finally, place this code at the end of the app-template.html file:
<sampleeleven></sampleeleven>
Now, you will start seeing a counter appear on the page.
The outputs property is used to define the events the component emits. We need to create a property in this keyword with the same name as the output and assign   it to a new instance of ng.core.EventEmitter so that it can emit events. ng.core. EventEmitter provides observer patterns to objects.
To capture events, we need to use the () token, just like we used it to capture native UI events.

Two-way data binding with inputs and outputs

You can implement two-way data binding between inputs and outputs. For example, if a parent component passes an attribute to a component of the view children
and the child component notifies the parent component whenever the input value
changes, then instead of using () and [] separately, we can use [()].
Here is an example to demonstrate this. Place this code above the App component’s code:
var SampleComponent12 = ng.core.Component({ selector: “sampletwelve”,
inputs: [“count”], outputs: [“countChange”], template: “”
}).Class({
constructor: function(){
this.countChange = new ng.core.EventEmitter(); setInterval(function(){
this.count++; this.countChange.next(this.count);
}.bind(this), 10000);
}
})

var SampleComponent13 = ng.core.Component({ selector: “samplethirteen”,
directives: [SampleComponent12], template: “<br><sampletwelve
[(count)]=’count’></sampletwelve>{{count}}”
}).Class({
constructor: function(){ this.count = 1;
}
})
Replace the App component’s code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4, SampleComponent6, SampleComponent7, SampleComponent8, SampleComponent9, SampleComponent11, SampleComponent13],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})

Finally, add this code to the end of the app-template.html file:
<samplethirteen></samplethirteen>
Here, the output is same as the previous example. Most of the things are self-explanatory. The only thing you need to know is that both these code snippets do the same thing:
<sampletwelve [(count)]=’count’></sampletwelve>
<sampletwelve [count]=’count’ (countChange)= ‘count=$event’></sampletwelve>

Understanding providers

A provider tells Angular 2 how to create an instance of a service while injecting it. A provider is set using the providers or viewProviders properties of a component.
Let’s look at an example of how to create providers. Place this code above the App
component’s code:
var Service1 = ng.core.Class({ constructor: function() {
},
getValue: function() { return “xyz”
}
});

var Service2 = ng.core.Class({ constructor: function() {
},
getValue: function() { return “def”
}
});

var Service3 = ng.core.Class({ constructor: function() {
},
getValue: function() { return “mno”
}
});

var Service4 = ng.core.Class({
constructor: [Service2, Service3, function(s2, s3) { console.log(s2);
console.log(s3);
}],
getValue: function() { return “abc”
}
});

var ServiceTest1 = ng.core.Component({ selector: “st1”,
viewProviders: [
ng.core.provide(Service1, {useClass: Service4}), ng.core.provide(Service2, {useValue: “def”}), ng.core.provide(Service3, {useFactory: function(){
return “mno”;
}})
],
template: “”
}).Class({
constructor: [Service1, function(s1){ console.log(s1.getValue());
}]
})
Replace the App component’s code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4, SampleComponent6, SampleComponent7, SampleComponent8, SampleComponent9, SampleComponent11, SampleComponent13,
ServiceTest1],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
Finally, add this to the end of the app-template.html file:
<st1></st1>

 

This is the console output of the code:
def mno abc
This is how it works:

  1. First, we create four services: Service1, Service2, Service3, and Service4. They all have a getValue method, which returns a string. Service4 is dependent on Service2 and Service3.
  2. Then, we create a component called ServiceTest1. It’s dependent on Service1. In the viewProviders property, we passed an array of providers. A provider is created using the ng.core.provide method. It takes two arguments; the first one is the service name, and the second one is the configuration object, which states how to create an instance of this service. The useClass property tells Angular 2 to create a instance of this service when an instance of the service in the first argument is requested. So here, when an instance of Service1 is required, an instance of Service4 is what is actually created. Similarly, useValue is used to provide a value, and useFactory is used to pass control to a function to decide what to return when a new instance is requested. So here, when an instance of Service2 is

requested, we get the def string, and when Service3 is requested, we get the
mno string.
Earlier in this article, we were simply assigning viewProviders to the services themselves. A service also implements the interface of a provider such that it creates the instance of the service itself.
If there are multiple providers matching a service, then the latest one overrides the previous one.

The difference between providers and the viewProviders property

The viewProviders property allows us to make providers available to the component’s view only, whereas the providers property makes a provider available to its content children and view children.
The providers property creates a service instance only once and provides the same to whichever component asks for it. We have already seen how viewProviders works. Let’s look at an example of how providers works. Place this code above the App component’s code:
var counter = 1;

var Service5 = ng.core.Class({ constructor: function(){}
})

var ServiceTest2 = ng.core.Component({ selector: “st2”,
template: “”
}).Class({
constructor: [Service5, function(s5){ console.log(s5);
}]
})

var ServiceTest3 = ng.core.Component({ selector: “st3”,
providers: [ng.core.provide(Service5, {useFactory: function(){ counter++;
return counter;
}})],
directives: [ServiceTest2], template: “<st2></st2>”
}).Class({
constructor: [Service5, function(s5){ console.log(s5);
}]
})
Replace the App component’s code with this:
var App = ng.core.Component({ selector: “app”,
directives: [Cards, SampleComponent1, List, ListItem, SampleComponent2, SampleComponent3, SampleComponent4, SampleComponent6, SampleComponent7, SampleComponent8, SampleComponent9, SampleComponent11, SampleComponent13, ServiceTest1, ServiceTest3],
templateUrl: “componentTemplates/app-template.html”
}).Class({
constructor: function(){}
})
Finally, at the end of the app-template.html file, place this code:
<st3></st3>
The console output of this code is as follows:
2
2
Most of the things in this code are self-explanatory. We are using providers instead of viewProviders. The ServiceTest2 component is dependent on Service5, but
it doesn’t have a provider for Service5, so Angular 2 uses the provider provided by ServiceTest3, as ServiceTest3 is its parent. If ServiceTest3 hadn’t had a
provider for Service5, Angular 2 would have gone further above and looked for the provider in the App component.

 

Summary

In this article, we learned about Angular 2. We saw what components are, how to write templates, how to create services, and so on. We also learned about web components and how Angular 2 takes advantage of them. You should now be comfortable with building Angular 2 applications.
For the next step, we will learn how to build an SPA using Angular 2 by building a complete App.

 

Here are related articles if you wish to learn more advance topics for web development:

Best practices for securing and scaling Node.JS applications
How Bootstrap 4 extensible content containers or Cards work
Comprehensive guide for migration from monolithic to microservices architecture
Comprehensive overview of Bootstrap 4 features for user interface customizations
Intro to functional reactive programming for advance js web development
Using advance js and webrtc for cross browser communications in real time
Intro to real-time bidirectional communications between browsers and webSocket servers

Junior or senior web developers can also explore career opportunities around blockchain development by reading below articles:

Blockchain Developer Guide- Comprehensive Blockchain Ethereum Developer Guide from Beginner to Advance Level
Blockchain Developer Guide- Comprehensive Blockchain Hyperledger Developer Guide from Beginner to Advance Level