Contents
- Introduction
- Breaking the surface: AngularJs Introduction
- Data Binding: ng-model, ng-bind and expression{{}}
- Modules
- Controllers
- Filters
- Repeaters
- Directives
- Communicating with Servers
- Routing
- Out of the Box
- End Note
Introduction
I have been working on AngularJs for quite some time and I have become amazed by the power of AngularJs. So I thought of this article to expose the power of AngularJs to you. I have tried to make this article as explanative as possible and it is written in a fast-track mode. That means it will give you a glimpse at some of the important topics of AngularJs in very less time.
Breaking the surface: AngularJs Introduction
AngularJs is a full-featured Single-Page Application (SPA) framework. It is a JavaScript framework. It is a library written in JavaScript. It turns a simple HTML page into a full-fleged Single-Page Application by adding some custom attributes (directives, we'll see them soon). I will not waste time by adding definitions and details from the Wikipedia because our main goal is to learn most of it in less time. So the following figure is a brief description of AngularJs.
As you can see from the diagram, there is much to learn about AngularJs but we will learn some of the very important and core topics.
Before we move forward, let me tell you what we will build. We will be building a very simple Single-Page Application of a Movies App and in the building process we will be covering the following topics:
- Data Binding
- Controllers
- Directives
- Filters
- Routing
- Template
- Retrieving data from Servers
Before we proceed the following is the procedure you need to follow to use AngularJs in your web application:
- Download the AngularJs minified JavaScript file or you can use the CDN in the HTML page. Please visit for downloading or for CDN.
- Load the angular.js library.
- ( <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.min.js">
- </script>
or
- <script src="angular.min.js"></script> )
- Tell Angular which part of the DOM it should manage with the ng-app directive.
Note: We will be doing all the preceding procedure in this article so just sit tight and let our Angular train begin.
Data Binding: ng-model, ng-bind and expression{{}}
Angular supports a Model View Controller style of application design.
- Model: A model containing data that represents the current state of your application.
- View: Views that display this data.
- Controllers: Controllers that manage the relationship between your model and your views.
Baby Step towards Angular
You can use any editor of your choice to build your Angular application. For the sake of simplicity I will be using Notepad++. First create a HTML page and add a script tag and load the AngularJs library. In the body tag create a container div then add a text box and a para to it. We need to add new attributes to the div and text box that are known as directives in AngularJs. See the code below. I will explain the meaning soon.
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8" />
- </head>
- <body>
- <script src="scripts\angular.min.js"></script>
- <!--AngularJs library is loaded.-->
- <div ng-app>
- <!-- New attribute ng-app(directive) to let browser know that this div is using angular js-->
- <input type="text" ng-model="Name" />
- <!--Attribute ng-model-->
- <p>{{Name}}</p>
- </div>
- </body>
- </html>
As you can see, we have two attributes (directives). The first one is ng-app that tells the browser which part of HTML is using AngularJs and the other one is ng-model that is binding the data (Name), so whatever you type in TextBox is stored in Name and will be displayed in the para using the expression. {{}} is the syntax of an expression. We can also do it using ng-bind in our para instead of expression.
OutputThat's it. Just by adding two new attributes and without writing any script we have created a fully functional app. That's the power of AngularJs.
The following are some definitions from
http://www.w3schools.com/.
- The ng-app directive initializes an AngularJs application.
- The ng-model directive binds the value of HTML controls (input, select, textarea) to the application data.
- The ng-bind directive binds the application data to the HTML view.
- AngularJs expressions bind data to HTML the same way as the ng-bind directive.
- AngularJs expressions are much like JavaScript expressions, they can contain literals, operators and variables. Example:
- 1. <p>{{5*2}}</p> Output:10
- 2. <span>{{“hello ”+ Name}}</span>
Output: hello [Value stored in Name].
Modules
Modules define an AngularJs application. They are a container for various parts of an application. Modules contain a special JavaScript Object called controllers that controls various parts of an application. A module can contain more than one controller as needed. Let's define our own module for our app as in the following:
- var app= angular.module(‘MovieApp’,[]);
Here MovieApp is the name of our module that we will require in the HTML page to let our HTML page know which ng-app to use. The [] brackets are used for dependency injection. In simple words we can inject here the name of other modules to which our module is depended upon.
- <!DOCTYPE html>
- <html ng-app="MovieApp">
- <head>
- <meta charset="utf-8" />
- </head>
- <body>
- <script src="scripts\angular.min.js"></script>
- <!--AngularJs library is loaded.-->
- </body>
- </html>
Controllers
Controllers are the mediator between the Model and the View. It controls the data and the Model to display on the View. We can say an AngularJs application is controlled by controllers. We can create logic to manipulate the Model in the controllers. Controllers can be classes or types we write in Angular of objects or variables make up our model by assigning them to the special object called $scope passed into our controller. Let's see a simple example:
- <!DOCTYPE>
- <html ng-app="MovieApp">
- <!--ng-app: this is an angular app , MovieApp is the Module Name-->
- <head>
- <title></title>
- </head>
- <body>
- <script src="scripts\angular.min.js"></script>
- <!--AngularJs library is loaded.-->
- <script>
- var app = angular.module("MovieApp", []);
-
- app.controller("MyCtrl", function ($scope)
- {
- $scope.MyModelData = "Hello, you can see me on View.";
-
- });
- </script>
- <div ng-controller="MyCtrl">
- <!--ng-controller for this div to contol model for it.-->
- <span ng-bind="MyModelData" ></span>
- <!--MyModelData is bind here using ng-bind to display on the span-->
- <p>
- <b>{{MyModelData}}</b>
- </p>
- <!--Expressions are used to bind MyModelData-->
- </div>
- </body>
- </html>
Filters
Filters help us to transform/format data for display in a View for the user to make it more readable and user-friendly. The syntax for filters is:
- {{ expression | filterName : parameter1 : parameter2 … }}
Some of the commonly used filters are currency, uppercase, lowercase, number and so on. You can find them all on AngularJs official website.
Let's see a live example to understand it better:
-
- <!DOCTYPE>
- <html ng-app="MovieApp">
- <!--ng-app: this is an angular app , MovieApp is the Module Name-->
- <head>
- <title></title>
- </head>
- <body>
- <script src="scripts\angular.min.js"></script>
- <!--AngularJs library is loaded-->
- <script>
- var app = angular.module("MovieApp", []);
-
- app.controller("MyCtrl", function ($scope)
- {
- $scope.Amount = "1000.00";
- $scope.Num = 500.000;
- $scope.Name = "Mr. xyZ";
-
- });
- </script>
- <div ng-controller="MyCtrl">
- <!--ng-controller for this div to contol model for it.-->
- <p>Amount: {{Amount | currency}}</p>
- <!--Filters used-->
- <p>Number without decimal digit:{{Num | number:0}}</p>
- <p>Number with one decimal digit: {{Num | number:1}}</p>
- <p>Number with two decimal digit: {{Num | number:2}}</p>
- <p>Name in uppercase: {{Name | uppercase}}</p>
- <p>Name in lowercase: {{Name | lowercase}}</p>
- <p></p>
- </div>
- </body>
- </html>
Output
Repeaters
Until now we saw some basic topics of Angular and now we will see possibly the most useful directive of Angular, ng-repeat, that creates a copy of a set of elements once for every item in a collection. I know you won't believe it until you see it so let's see a live example as in the following:
- <!DOCTYPE>
- <html ng-app="MovieApp"><!--ng-app: this is an angular app , MovieApp is the Module Name-->
- <head>
- <title></title>
- </head>
- <body>
- <script src="scripts\angular.min.js"></script>
- <script>
- var app = angular.module("MovieApp", []);
-
- app.controller("MyCtrl", function ($scope)
- {
- $scope.Movies = [
- {MovieName:"The Dark Knight", Rating : 8.4},
- {MovieName:"Dark Knight Rises", Rating : 8.1},
- {MovieName:"The Fight Club", Rating : 8.3},
- { MovieName: "Mad Max Fury", Rating: 8.2 },
- { MovieName: "Warrior", Rating: 8.4 }
- ];
-
- });
- </script>
- <div ng-controller="MyCtrl"><!--ng-controller for this div to contol model for it.-->
-
- <ul ng-repeat="mov in Movies"><!--ng-repeat is used to loop for items in Movies object-->
- <li>{{mov.MovieName}}</li><!--Only one li item is created here but at run 5 li will be created-->
- </ul>
-
- <!--ng-repeat for tables-->
- <table border="1">
- <thead>
- <tr>
- <th>Name</th><th>Ratings</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat= "mov in Movies"><!--Only one row is created here but rest will created automatically-->
- <td>{{mov.MovieName | uppercase}}</td>
- <td>{{mov.Rating}}</td>
- </tr>
- </tbody>
- </table>
-
- </div>
- </body>
- </html>
OutputThe preceding code is self-explanatory but let me clarify it for you. As you can see the <ul> loops through all the items and creates a <li> for each item present in the object. The same thing happened in the table, the <tr> looped through all the items and rows will be created at runtime.
Directives
With directives we can extend the HTML syntax, we can create our custom elements and attributes to associate the behavior and DOM transformations. We can create reusable UI components and templates that suits our application needs. In fact, until now we have used Angular's built-in directives with the ng-directive-name syntax. Examples include ng-model, ng-repeat, ng-controller, ng-app. Here ng is the namespace for Angular and the part after the dash is the name of the directive.
Well enough talk, let's create our own simple directive or usable component as in the following:
- <!DOCTYPE>
- <html ng-app="MovieApp"><!--ng-app: this is an angular app , MovieApp is the Module Name-->
- <head>
- <title></title>
- </head>
- <body>
- <script src="scripts\angular.min.js"></script>
- <script>
- var app = angular.module("MovieApp", []);
-
- app.directive("banner", function () {
-
- return {
-
- restrict: 'E',
- template: '<h1>Hello World!!</h1><h2>My first Directive</h2>',
- link: function (scope,element,attribute) {
- element.bind("mouseenter", function () { alert("Hi, there!!") })
- }
-
- }
-
- });
- </script>
- <div >
- <banner></banner><!--Directive implemented-->
- </div>
- </body>
- </html>
OutputLet's see the property used to build our directive.
Restrict
Restrict specifies how the directive will be used in a template as an element (E), attribute (A), class (C) or comment (M). In our example we created an element by setting the restrict property to "E". So we can create our custom attribute, class and comment for HTML elements.
TemplateTemplate specifies an inline template as a string. We have added two heading tags.
Link
A Link programmatically modifis the DOM element instances and adds event listeners and sets up data binding.
Here we have created a very simple usable template called banner element that contains two headings, <h1> and <h2>. If you inspect an element tehn you can easily determine the <banner> tag. The interesting thing is that here <banner> is not an actual HTML tag but still your browser is showing the output. If you want to hide the <banner> tag and just want to show the <h1> and <h2>, you can also do that by just adding one more property to your directive, "
replace : true". We have also linked a function to our directive that takes the three parameters, the scope of that directive, the element that is our directive and the attribute of our directive. In this function we have bound the mouseenter event to our element and on mouseenter it gives an alert.
We have used only three properties in our directive but they are not limited to three, there are more properties that we can use for making our custom directive. But unfortunately we are not explaining them in this article because it's just an introduction article and I don't want to make things complicated here but maybe in the future I will return with another article explaining all that we have left here.
Communicating with Servers
Nearly every app needs to communicate with a server to fetch some data or to post some data. For this Angular provides a service called $http. It provides abstraction that makes it easier to talk to servers. Let's say we need to retrieve a movies list for our app from a server instead of from variables or in-memory mocks. So all we need is the service that can provide the movie list in JSON format when we query Angular. Since we do not have such a service we will retrieve our data from a JSON file in our app. Here I am just showing you the syntax for using $http, we will see a complete example when we start building our app.
- $http.get(ServiceURL).success(function (data, status, headers, config) {
-
-
-
- });
The preceding is very simple syntax to get data from a server.
Routing
In a Single-Page Application, the HTML page is loaded on the first request, then only some areas within the DOM are updated. In a SPA we usually have multiple sub-page views or templates that we show or hide from the user appropriately. For this in Angular we have $route to handle such scenarios. Using $route we specify that, for a given URL that the browser points to, Angular should load and display a template and instantiate a controller to provide context for the template.
We can create routes in our app using the
$routeProvider service as a configuration block for an Angular module in our application.
Let's quickly see its syntax as in the following:
- app.config(function ($routeProvider) {
- $routeProvider.
- when('/', {
- templateUrl: 'path of html',
- controller: 'AppCtrl'
-
- }).
- when('/first', {
- templateUrl: 'path of template 1 html',
- controller: 'Ctrl1'
- }).
- when('/second', {
- templateUrl: 'path of template 2 html',
- controller: 'Ctrl2'
- }).
- otherwise({
- redirectTo: '/'
- });
-
-
- });
The syntax is much easier here when the browser points to "/". The main HTML page is loaded and the controller "AppCtrl" is loaded and when the browser points to "/first" the HTML page containing template 1 is loaded into the main page in the <ng-view></ng-view> directive defined on the page. I know at this point it's kind of hard to understand without an example but don't worry, for now just concentrate on the syntax, we will be seeing soon the working example of it.
Out of the Box
As I promised here, we are ready to create our first AngularJs app. I will be using all the concepts that we have discussed above. Since this will be our first app I have tried to make things as simple as possible. We will be creating a movie app that will show the names of movies in a table and you can determine more about any movie by clicking on its name.
The following is the screen-shot of what we will build:
The following is the folder structure of our app:
Step 1: index.html
Create a HTML page named it index.html. Link CSS file. Load the AngularJs Library. I have used two files to load the library, one is angular.min.js and the other is angular-route.js that we will require for routing. Also load our app script file. Add an attribute to the ng-app=”MovieA” that we tell the browser that this page is an Angular app. This page is very simple, nothing is in it except for the logo div and our custom directive <banner> and the <ng-view> directive of Angular.
- <!DOCTYPE html>
- <html ng-app="MovieApp">
- <head>
- <meta charset="utf-8" />
- <title>AngularJS Movies App</title>
- <link href="css\Style.css" rel="stylesheet" />
- </head>
- <body>
- <script src="scripts\angular.min.js"></script>
- <script src="scripts\angular-route.js"></script>
- <script src="scripts\script.js"></script>
- <div>
- <!---Logo div of our app-->
- <div class="header">
- <img src="img\logo.png" style="width: 200px;" />
- </div>
-
- <!--Custom directive-->
- <banner></banner>
-
- <!--ng-view to load different templates here using routing-->
- <ng-view></ng-view>
-
- </div>
- </body>
- </html>
Step 2: style.css
The CSS is also very simple. I hope you will understand it easily.
- body {
- color: #204056;
- }
-
- a {
- color: #204056;
- }
- .header {
- width: 100%;
- background-color: #39d1b4;
- height: 50px;
- padding: 0px;
- margin: 0px;
- }
-
- h2{
- margin-left:40%;
- }
- h3 {
- margin-left:38%;
- }
-
- .myborder
- {
- border-radius: 18px 17px 14px 21px;
- border: 5px solid #39D1B4;
- }
-
- p
- {
- margin-left: 14px;
- font-family: "Comic Sans MS",Arial,Helvetica,sans-serif;
-
- }
-
- span
- {
- color: #0066FF;
- font-size: 1.3em;
- }
- #movies {
- margin-top:5px;
- font-family: "Comic Sans MS", Arial, Helvetica, sans-serif;
- width: 100%;
- border-collapse: collapse;
- }
-
- #movies td, #movies th {
- font-size: 1em;
- border: 1px solid #204056;
- padding: 3px 7px 2px 7px;
- }
-
- #movies th {
- font-size: 1.1em;
- text-align: left;
- padding-top: 5px;
- padding-bottom: 4px;
- background-color: #39d1b4;
- color: #ffffff;
- }
-
- #movies tr.alt td {
- color: #000000;
- background-color: #C4F1E8;
- }
Step 3: script.js
Let's first create a module for our app.
- var app = angular.module('MovieApp', ['ngRoute']);
ngRoute is injected here for routing.
Then create our custom directive <banner>.
- app.directive("banner", function () {
- return {
- restrict: 'E',
- template: '<h2>AngularJS is fun!!</h2> <h3>HTML enhanced for web apps!</h3>',
-
- }
-
- })
Then the config of the app is defined for the routing for the various HTML templates are done. The point to see here is that when defining the route for movie.html we have passed the parameter :movieName, we will pass the value of it depending upon the movie name. The routing is very simple, when the browser points to "/" then movielist.html and its controller MoviesCtrl is loaded and when the browser points to "/movie/:movieName" then movie.html and MovCtrl are loaded.
- app.config(function ($routeProvider) {
- $routeProvider.when('/',
- {
- templateUrl: 'partials/part1/movieslist.html',
- controller: 'MoviesCtrl'
- })
- .when('/movie/:movieName',
- {
- templateUrl: 'partials/part2/movie.html',
- controller: 'MovCtrl'
- })
- });
So let's create a Controller for movielist.html. In this Controller we have passed $scope, $http and $location objects as parameters. $scope binds the data from the View, $http gets the data from the server (in our case it is from a JSON file), $location changes the URL in the browser.
The $http.get method is loading the data from the JSON file and filling in the movielist array.
We have also created a method $scope.redirectTo that takes the movie name as an argument and passes it to the $location.path that will change the URL in the browser and hence the template (movie.html) is loaded.
- app.controller('MoviesCtrl', function ($scope, $http, $location) {
- $scope.movieslist = [];
- $http.get('data/movies.json').success(function (data) {
-
- $scope.movieslist = data;
-
- });
- $scope.redirectTo = function (movieName) {
- $location.path('/movie/' + movieName);
-
- }
- });
Another controller is for movie.html. Let's create it too. The same parameters are passed as the previous one. The array $scope.movie is created. We will grab the movie name from the URL in the browser using $location.path, find the last index of "/" and then substring the movie name from the URL.
- var title = $location.path().substring($location.path().lastIndexOf('/')+1);
Again data is fetched from the JSON file but this time we will only fill the array with specific movie data, I mean the data of that movie of the title extracted from the URL. When the array is filled we will use $scope to bind the data from the View. We are iterating the objects fetched from the JSON file and check if the title of the object (movie) matches, if it matches then we put it into the array.
- app.controller('MovCtrl', function ($scope, $http, $location) {
- $scope.movie = [];
- var title = $location.path().substring($location.path().lastIndexOf('/') + 1);
-
- $http.get('data/movies.json').success(function (data) {
-
- angular.forEach(data, function (array) {
- if (array["Title"] == title) {
- $scope.movie = array;
- }
-
- });
- $scope.Title = $scope.movie["Title"];
- $scope.Year = $scope.movie["Year"];
- $scope.Released = $scope.movie["Released"];
- $scope.Runtime = $scope.movie["Runtime"];
- $scope.Actors = $scope.movie["Actors"];
- $scope.Director = $scope.movie["Director"];
- $scope.Plot = $scope.movie["Plot"];
- $scope.Genre = $scope.movie["Genre"];
- $scope.Writer = $scope.movie["Writer"];
- $scope.Awards = $scope.movie["Awards"];
- $scope.Language = $scope.movie["Language"];
- $scope.imdbVotes = $scope.movie["imdbVotes"];
- $scope.imdbRating = $scope.movie["imdbRating"];
-
- });
-
- });
The following is the complete script of our script.js:
- var app = angular.module('MovieApp', ['ngRoute']);
-
-
-
-
- app.directive("banner", function () {
- return {
- restrict: 'E',
- template: '<h2>AngularJS is fun!!</h2> <h3>HTML enhanced for web apps!</h3>',
-
- }
-
- })
-
-
-
-
- app.config(function ($routeProvider) {
- $routeProvider.when('/',
- {
- templateUrl: 'partials/part1/movieslist.html',
- controller: 'MoviesCtrl'
- })
- .when('/movie/:movieName',
- {
- templateUrl: 'partials/part2/movie.html',
- controller: 'MovCtrl'
- })
- });
-
-
-
-
-
-
- app.controller('MoviesCtrl', function ($scope, $http, $location) {
- $scope.movieslist = [];
- $http.get('data/movies.json').success(function (data) {
-
- $scope.movieslist = data;
-
- });
- $scope.redirectTo = function (movieName) {
- $location.path('/movie/' + movieName);
-
- }
- });
-
-
-
-
- app.controller('MovCtrl', function ($scope, $http, $location) {
- $scope.movie = [];
- var title = $location.path().substring($location.path().lastIndexOf('/') + 1);
-
- $http.get('data/movies.json').success(function (data) {
-
- angular.forEach(data, function (array) {
- if (array["Title"] == title) {
- $scope.movie = array;
- }
-
- });
-
- $scope.Title = $scope.movie["Title"];
- $scope.Year = $scope.movie["Year"];
- $scope.Released = $scope.movie["Released"];
- $scope.Runtime = $scope.movie["Runtime"];
- $scope.Actors = $scope.movie["Actors"];
- $scope.Director = $scope.movie["Director"];
- $scope.Plot = $scope.movie["Plot"];
- $scope.Genre = $scope.movie["Genre"];
- $scope.Writer = $scope.movie["Writer"];
- $scope.Awards = $scope.movie["Awards"];
- $scope.Language = $scope.movie["Language"];
- $scope.imdbVotes = $scope.movie["imdbVotes"];
- $scope.imdbRating = $scope.movie["imdbRating"];
-
- });
-
- });
Step 4: Templates
Let's create templates that will be loaded on our index.html. Create a div and define its attribute ng-controller. Add an input box and set its ng-model to "mov" that will filter the name of the movie. Add a table, ng-repeat is used to create rows automatically based on the object on the movieslist array. We have also used ng-class to add a CSS style if the row is odd using $even.
- <div ng-controller="MoviesCtrl">
- <input type="text" ng-model="mov" style="width:300px;" placeholder="Search" />
- <img src="img\srch.png" style="width:15px;height:15px;" />
- <br />
- <table id="movies">
- <thead>
- <tr>
- <th>Movies Name</th>
- <th>Year</th>
- <th>Genre</th>
- <th>Rating</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-repeat="t in movieslist| filter:mov " ng-class="$even ? '' : 'alt'">
- <td><a href='' ng-click='redirectTo(t.Title)'>{{t.Title}} </a></td>
- <td>{{t.Year}}</td>
- <td>{{t.Genre}}</td>
- <td>{{t.imdbRating}}</td>
-
- </tr>
- </tbody>
- </table>
-
-
- </div>
Now create a second template that will display the complete information of a specific movie selected by the user from the list of movies table. Its a simple HTML template containing div, paras and span to display movie information but an important point here is that all the paras are bound to the model using an expression.
- <div class="myborder">
- <p><span>Title:</span> {{Title}}</p>
- <p><span>Year:</span> {{Year}}</p>
- <p><span>Released:</span> {{Released}}</p>
- <p><span>Runtime:</span>{{Runtime}}</p>
- <p><span>Genre:</span>{{Genre}}</p>
- <p><span>Actors:</span> {{Actors}}</p>
- <p><span>Director:</span> {{Director}}</p>
- <p><span>Writer:</span> {{Writer}}</p>
- <p><span>Awards:</span> {{Awards}}</p>
- <p><span>Language:</span> {{Language}}</p>
- <p><span>Votes:</span> {{imdbVotes}}</p>
- <p><span>Rating:</span> {{imdbRating}}</p>
- </div>
That's it! We are good to go now. Run index.html in a Firefox Mozilla browser because in Chrome you may get a cross-domain error or you can host the app on IIS and test it on any browser.
End Note
We created a simple app by writing very few lines of script and HTML. I hope my effort to expose the power of AngularJs helps to understand it better and you can use it for your personal or corporate apps.