Recipe ID: hsts-r47
We offer HTML5, CSS3, JavaScript,Bootstrap, Angular.JS, WordPress Node.JS, React.JS, Joomla, Drupal, Vue.JS and more classes in self-paced video format starting at $60. Click here to learn more and register. For complete self-paced web design training, visit our Web design and development bundle page.
To build single page applications (SPAs) using Angular 2, we need to learn how to implement routing in Angular 2. Angular 2 comes with built-in routing APIs, which are very powerful, feature rich, and easy to use. In this recipe, we will build a basic search engine template to demonstrate routing in Angular 2. We won't be building a complete search engine because that's out of the scope of this recipe. We will use Bootstrap 4 to design the search engine template. At the end of this recipe, you will be comfortable with building SPAs using Angular 2.
Before working on this tutorial, reading Comprehensive overview of Angular 2 architecture and features is highly recommended.
In this recipe, we will cover the following topics:
Follow these steps to set up your project:
package.json file, place this code:
{
"name": "SearchEngine-Template", "dependencies": {
"express": "4.13.3",
"chance": "1.0.3"
}
}
Here, we are listing Express.js and Chance.js as dependencies. Express will be used to build the web server whereas Chance.js will be used to generate random textual data to populate the template's search results.
Inside the initial directory, you will find a directory named public, inside which all the static assets will be placed. Inside the public directory, you will find the componentTemplates, css, html, and js directories.
Inside the css directory, you will find bootstrap.min.css; index.html inside the html directory; and finally, index.js, angular2-all.umd.js, angular2-polyfills.js, and Rx.umd.js inside the js directory.
index.js file:
<!doctype html>
<html>
<head>
<title>Search Engine Template</title>
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
</head>
<body>
<script src="/js/angular2-polyfills.js"></script>
<script src="/js/Rx.umd.js"></script>
<script src="/js/angular2-all.umd.js"></script>
<script src="/js/index.js"></script>
</body>
</html>
This code is self-explanatory.
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);
Here as well, most of the code is self-explanatory. We are simply serving
index.html regardless of what the HTTP request path is.
In SPA, the routes for our app are defined in the frontend. In Angular 2, we need to define the paths and a component associated with the path that will be rendered for that path.
We provide the routes to the root component, and the root component displays the component bound to the route.
Let's create the root component and routes for our search engine template:
and routes:
var AppComponent = ng.core.Component({ selector: "app",
directives: [ng.router.ROUTER_DIRECTIVES], templateUrl: "componentTemplates/app.html"
}).Class({
constructor: function(){}
})
AppComponent = ng.router.RouteConfig([
{ path: "/", component: HomeComponent, name: "Home" },
{ path: "/search-result", component: SearchResultComponent, name: "SearchResult" },
{ path: "/*path", component: NotFoundComponent, name: "NotFound" }
])(AppComponent);
ng.platform.browser.bootstrap(AppComponent, [ ng.router.ROUTER_PROVIDERS, ng.core.provide(ng.router.APP_BASE_HREF, {useValue : "/" })
]);
<nav class="navbar navbar-light bg-faded">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" [routerLink]="['Home']">Home</a>
</li>
</ul>
</nav>
<router-outlet></router-outlet>
Here is how this code works:
To populate our template, we need to generate some random search result data. For this, we can use the Chance.js library. We will generate random data on the server side, not on client side, so that we can later demonstrate how to make an HTTP request using Angular 2.
Chance.js is available for both client-side and server-side JavaScript. We earlier downloaded the Chance.js package to use with Node.js. Here is the code to generate random data. Place it in the app.js file above the /* route so that /* doesn't override the random data route:
var Chance = require("chance"), chance = new Chance();
app.get("/getData", function(httpRequest, httpResponse, next){ var result = [];
for(var i = 0; i < 10; i++)
{
result[result.length] = { title: chance.sentence(), desc: chance.paragraph()
}
}
httpResponse.send(result);
})
Here, we first create a route for the /getData path, which sends an array of search results as a response. The route callback uses chance.sentence() to generate random titles for the search result and chance.paragraph() to generate a description.
Let's create HomeComponent, SearchResultComponent, and NotFoundComponent. Before that, let's create a component to display the search form. The search form will have a textbox and a search button. Follow these steps:
var FormComponent = ng.core.Component({ selector: "search-form",
directives: [ng.router.ROUTER_DIRECTIVES], templateUrl: "componentTemplates/search-form.html",
}).Class({
constructor: function(){}, ngOnInit: function(){
this.searchParams = { query: ""
};
this.keyup = function(e){ this.searchParams = {
query: e.srcElement.value
};
};
}
})
directory, and place this code in it:
<div class="m-a-2 text-xs-center">
<h1>Search for Anything</h1>
<form class="form-inline m-t-1">
<input (keyup)="keyup($event)" class="form-control" type="text" placeholder="Search">
<a [routerLink]="['SearchResult', searchParams]">
<button class="btn btn-success-outline" type="submit">Search</button>
</a>
</form>
</div>
This is how the code works:
ng.router.ROUTER_DIRECTIVES directive.
searchParams.query property.
Now, let's create the HomeComponent component. This component is displayed on the home page. It displays the search form.
Here is how to create HomeComponent:
var HomeComponent = ng.core.Component({ selector: "home",
directives: [FormComponent],
templateUrl: "componentTemplates/home.html",
}).Class({
constructor: function(){}
})
componentTemplates directory:
<search-form></search-form>
Here, the HomeComponent code is self-explanatory.
var SearchResultComponent = ng.core.Component({ selector: "search-result",
directives: [FormComponent], viewProviders: [ng.http.HTTP_PROVIDERS],
templateUrl: "componentTemplates/searchResult.html"
}).Class({
constructor: [ng.router.RouteParams, ng.http.Http, function(params, http) {
this.params = params; this.http = http; this.response = [];
}],
ngOnInit: function(){
var q = this.params.get("query"); this.http.get("getData").subscribe(function(res){
this.response = JSON.parse(res._body);
}.bind(this));
}
})
componentTemplates. Place this code in the file:
<style>
ul
{
list-style-type: none;
}
</style>
<div class="container">
<search-form></search-form>
<div class="m-a-2 text-xs-center">
<ul>
<li *ngFor="#item of response" class="m-t-2">
<h4>{{item.title}}</h4>
<p>{{item.desc}}</p>
</li>
</ul>
</div>
</div>
This is how the code works:
Now, let's create NotFoundComponent. Here is the code for that:
var NotFoundComponent = ng.core.Component({ selector: "name-search",
templateUrl: "componentTemplates/notFound.html"
}).Class({
constructor: function(){}
})
componentTemplates directory. Place this code inside the file:
<div class="container">
<div class="m-a-2 text-xs-center">
<h1>The page your are looking for is not found</h1>
</div>
</div>
The code is self-explanatory.
To test the template, we will follow these steps:
When a path matches a component, Angular 2 activates the component, and when the path changes, Angular 2 deactivates it. When we say that a component has been activated, it means that Angular 2 has created an instance of the component, that is, called the constructor method of the component, whereas when we say a component has been deactivated, it means the component has been removed from the DOM and instance is deleted.
The methods of a component that are called while activating or deactivating it are called routing lifecycle methods.
Here is the list of routing lifecycle methods:
Let's look at a code example of the routing lifecycle methods. Replace the
HomeComponent code with this:
var HomeComponent = ng.core.Component({ selector: "home",
directives: [FormComponent],
templateUrl: "componentTemplates/home.html",
}).Class({
constructor: function(){}, routerOnActivate: function(){
console.log("Component has been activated");
},
routerCanReuse: function(){ console.log("Component can be reused"); return true;
},
routerOnReuse: function(){ console.log("Component is being reused");
},
routerCanDeactivate: function(){ console.log("Component can be deactivated"); return true;
},
routerOnDeactivate: function(){ console.log("Component has been deactivated");
}
})
HomeComponent = ng.router.CanActivate(function(){ console.log("Component can be activated"); return true;
})(HomeComponent);
Now, visit the home page. There, click on the home button again. Now, type something in the search box and click on the Search button. This is the console output you will see:
Component can be activated Component has been activated Component can be reused Component is being reused Component can be deactivated Component has been deactivated
Until now, we have been running Angular 2 in development mode. The difference between development and production mode is that in development mode, Angular 2 starts change detection immediately after the first run and logs a value has changed after it was checked error if anything changes between the first and second run. This helps locate bugs.
To enable production mode, place this code above the ng.platform.browser. bootstrap() method call:
ng.core.enableProdMode();
In this recipe, we learned routing in Angular 2 by building a basic search engine template. Along with learning routing in depth, we also learned about the Angular 2 HTTP client service as well as how to switch to production mode in Angular 2.
You should now be comfortable with building the frontend of any kind of web application using Angular 2.
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
Here are more hands-on recipes for advance web development:
Develop microservices with monolithic core via advance Node.JS
Develop server-side applications using microservices with Seneca.JS
Advance UI development with JS MVC framework and react
Develop advance JavaScript applications with functional reactive programming
Develop advance webcam site using Peerjs and Peerserver with Express.JS
Develop advance bidirectional communication site with websockets and Express.JS
This recipe is developed by Narayan Prusty who is our senior Blockchain instructor.
Hands-on Node.JS, MongoDB and Express.js Training
Advance JavaScript, jQuery Using JSON and Ajax
Developing Web Applications Using Angular.JS
Design websites with JavaScript React in 30 hours
Blockchain Certified Solution Architect in 30 hours
Advance JavaScript, jQuery Using JSON and Ajax
Introduction to Python Programming
Object Oriented Programming with UML
We offer private coding classes for beginners online and offline (at our Virginia site) with custom curriculum for most of our classes for $59 per hour online or $95 per hour in virginia. Give us a call or submit our Private Coding Classes for Beginners form to discuss your needs.