Click here to Skip to main content
15,888,610 members
Articles / Web Development / HTML

Getting Started with AngularJS - Part I

Rate me:
Please Sign up or sign in to vote.
4.72/5 (17 votes)
15 Oct 2015CPOL8 min read 23.2K   530   36   4
This article will demonstrate how to get started developing websites with AngularJS.

Introduction

In this article, we will see how to use AngularJS for building websites. It scopes for beginners who want to start with AngularJS and explains some basic features of AngularJS framework. I consider a simple CRUD example for products. I explained all the code segments used in this demonstration, then you can download the source code to get angularjs in action yourself.

Background

AngularJS is JavaScript MVC framework extensively used these days, and provides a powerful mechanism to develop responsive websites more quickly and more easily. Being the MVC framework, it provides you the way to distribute website code in three components, i.e., Model, Views & Controllers. So you have clear separations between data model, application logic (controllers) and the view presentation, makes it easy to focus on your primary development area. The view receives data from the model for display. When a user interacts with the application by clicking or typing, the controller responds by changing data in the model. Finally, the view gets notified that a change has occurred in the model so that it can update the displayed content.

In Angular applications, the view is the Document Object Model, the controllers are JavaScript classes, and the model data is stored in object properties. AngularJS ships the HTML template and data to the browser to be assembled at client side. With libraries like jQuery, you have to interact with DOM in order to update UI with the fresh model state, i.e., whenever you observe any change in the model, you have to interact with DOM to reflect the changes. While AngularJS provides us Data-Binding, we don't have to move data from one part to another, only we have to map the UI parts with JavaScript properties and it will be sync automatically.

Using the Code

Let's start with the code, we will move step-by-step from scratch to build a sample CRUD operations example.

Add index.html page with ng-app attribute in html tag, as:

HTML
<html ng-app="demoApp">

This will define our html page as angularjs application. Since angularjs is primarily a single page application framework, it will use html view templates as partial views in response to a certain route. To render a partial view, we use an attribute data-ng-view for a div tag, all our partial views will be rendered within this div tag.

HTML
<div data-ng-view=""></div>

Download two files angular.js and angular-route.js and add references to these files in index.html page. Or alternatively, you can directly add references to https://angularjs.org/ site as:

HTML
<script type="text/javascript"
src="http://code.angularjs.org/1.2.13/angular.js"></script>
<script type="text/javascript"
src="http://code.angularjs.org/1.2.13/angular-route.js"></script>

Partial Views

Now move to the real content for our CRUD example, we will develop two partial views, ProductListing.html and ProductEdit.html. Let's review the ProductListing html:

HTML
<div class="container">
    <h2 class="page-title">Products Listing</h2>

    <div class="searchbar">
        <ul class="entity-tabular-fields">
            <li>
                <label>Search: </label>
                <span class="field-control">
                    <input type="text" data-ng-model="filter.productName" />
                </span>
                <label></label>
            </li>
        </ul>
    </div>
    <h2><a href="#/ProductEdit">Add new product</a></h2>

    <table class="items-listing">
        <thead>
            <tr>
                <th>Code
                </th>
                <th>Name
                </th>
                <th>Description
                </th>
                <th>Category
                </th>
                <th>Action
                </th>
            </tr>
        </thead>
        <tbody>
            <tr data-ng-repeat="product in products | filter:filter.productName">
                <td><a href="#/ProductEdit?code=
                {{product.code}}">{{product.code}}</a></td>
                <td>{{product.name}} </td>
                <td>{{product.description}} </td>
                <td>{{product.category}} </td>
                <td><a href="#/?code={{product.code}}">Delete</a></td>
            </tr>
        </tbody>
    </table>
</div>

Image 1

Apart from html or CSS stuff, focus on angular directives, in <tbody> tag, we use the directive data-ng-repeat="product in products | filter:filter.productName". Where 'products' is our JavaScript array, serves here like in-memory data storage. This directive tells the JavaScript to loop through each array item and generate the <tr> tags for each individual item. Then, we added a filter with to get filter our items with respect to the productName within arbitrary filter object, as you might have noticed this is what object property we have binded our search textbox in the upper part of this ProductListing view by using the data binding directive data-ng-model="filter.productName", so whatever user types in this search box, products array will be filtered with the matching strings. To output any value to the html, we use the angular's data binding syntax {{VAULE_TO_BE_OUTPUT}}, like we displayed the products properties in table cells:

HTML
<td>{{product.name}} </td>

For the first cell, we display product.code and make it a link to our second partial view ProductEdit.html. And the last cell also contains a link to the same listing page with product code in the query string. We will later see the JavaScript code for our models / controllers, let's first review the ProductEdit partial view. Here is the content for ProductEdit.html:

HTML
<div class="container">

    <h2 class="page-title">Product Edit</h2>
    <br />

    <ul class="entity-tabular-fields">
        <li class="entity-field-row">
            <label>Product Code: </label>
            <span class="field-control">
                <input type="text" data-ng-model="currentProduct.code" />
            </span>
            <label></label>
        </li>
        <li class="entity-field-row">
            <label>Product Name: </label>
            <span class="field-control">
                <input type="text" data-ng-model="currentProduct.name" />
            </span>
            <label></label>
        </li>
        <li class="entity-field-row">
            <label>Description: </label>
            <span class="field-control">
                <input type="text" 
                data-ng-model="currentProduct.description"  aria-multiline="true"/>
            </span>
            <label></label>
        </li>
        <li class="entity-field-row">
            <label>Category: </label>
            <span class="field-control">
                <input type="text" data-ng-model="currentProduct.category" />
            </span>
            <label></label>
        </li>
        <li class="entity-field-row">
            <label></label>
            <span class="field-control">
                <button data-ng-click="saveProduct()">Save</button>
            </span>
            <label></label>
        </li>
    </ul>

</div>

Image 2

Notice the data-ng-model attribute we added for all input tags, this binds the model(product) properties with the UI elements. In this case, it is automatically created a new product object named currentProduct and populates its properties with the values user put in these input controls. In the end, you see a button tag with attribute data-ng-click which binds the button's click event with saveProduct() function inside the current $scope. Now you see $scope, this you can think of as a special JavaScript object, all our current view's required objects/methods are binded to $scope object, anything we declared within $scope object we can access from our views. You will get more clear when we proceed further with the model/controllers code.

JavaScript / Angular Part

Now let's move to the JavaScript part of code, earlier you added references for two AngularJS libraries, now add another JavaScript file, let's say main.js and add reference to the same index page. You can download the code attached, here I continue discussion with small parts.

First, declare our application object by calling angular.module.

JavaScript
var demoApp = angular.module('demoApp', ['ngRoute']);

The first parameter 'demoApp' is the name of the module we defined, and second parameter is any array of dependencies which are required by our module, in our case we have only one dependency 'ngRoute' for the scope of this article.

Next, we configure the routes for partial views:

JavaScript
 // Setup config routes
demoApp.config(function ($routeProvider) {
    $routeProvider
      .when('/',
      {
          controller: 'ProductController',
          templateUrl: 'partials/ProductListing.html'
      })
      .when('/ProductEdit',
      {
          controller: 'ProductController',
          templateUrl: 'partials/ProductEdit.html'
      })
      .otherwise({
          redirectTo: '/'
      });
});

Parameter $routeProvider is passed to the function for routes configuration, then uses a chain of .where() functions to look for url path and passes an object to define the target partial view with associated controller. Controller property defines which controller is going to be used by the partial view specified in templateUrl property. In our case, we are only using one controller, i.e., ProductController. otherwise() function defines the default partial view to be rendered if none of the specified paths is matched with the URL path being requested.

It's time to define ProductController, in AngularJS, you can have multiple ways to define a controller, we are using a controllers object, add all our controllers to this object and then finally setup this object to our app module's controllers.

JavaScript
// Define Controllers object
var controllers = {};

//add no.of controllers to this object, we are only using one controller: ProductController.
controllers.ProductController = function ($scope, $route, $routeParams, $location, ProductFactory) {
}

// Assign Controllers object to the app module
demoApp.controller(controllers);

Here is our ProductController's definition:

JavaScript
controllers.ProductController = function ($scope, $route, $routeParams, $location, ProductFactory) {

    $scope.products = [];
    
    var init = function () {
        $scope.products = ProductFactory.getProducts();
    };

    var initProductEdit = function () {
        var code = $routeParams.code;
        if (code == undefined) {
            $scope.currentProduct = {};
        }
        else {
            $scope.currentProduct = ProductFactory.loadProductByCode(code);
        }
    };

    $scope.$on('$viewContentLoaded', function () {
        var templateUrl = $route.current.templateUrl;
        if (templateUrl == "partials/ProductEdit.html") {
            initProductEdit();
        }
        else if (templateUrl == "partials/ProductListing.html") {
            var code = $routeParams.code;
            if (code != undefined) {
                
                $scope.deleteProduct(code);
            }
        }
    });

    init();

    $scope.saveProduct = function () {

		ProductFactory.saveProduct($scope.currentProduct);
		$location.search('code', null);
		$location.path('/');
    };

    $scope.deleteProduct = function (code) {

        ProductFactory.deleteProduct(code);
		$location.search('code', null);
        $location.path('/');
    };
};

Each controller has to pass a parameter named $scope, which is used by view to access data model. Anything that you define within the $scope object, you can directly access from the view. There are also some other optional parameters $route, $routeParams, $location that you can use if you need.

We added supporting functions in this controller to interact with ProductFactory, and make these functions accessible from view by adding to the $scope object. We used an event '$viewContentLoaded', this event is fired when any partial view is being loaded in our div tag. Since I am using the ProductEdit page for both add/edit tasks, I put query string parameter for product code to be edited. I check in this event if we have query parameter code then the view is in editing mode, otherwise it is about to create a new product. Similar technique is used for delete task on ProductListing view, i.e., if we have code in the query string parameter, then we will delete that product and refresh the listing table.

Another parameter you might have noticed in the controller function is ProductFactory, this is the service component we need to access data from our controller. Angular framework allows the creation of a service component in different ways. The most common way is to create it using a factory. We need to add the service in the application module that passes two parameters: the name of the service and the factory function. It is a simple function that returns a new object. Here is the ProductFactory definition:

JavaScript
// Define Factory
demoApp.factory('ProductFactory', function () {
	
	//this is our proudcts array containing items, here we can change to get data from the server.
    var products = [
      { code: 'P001', name: 'Laptop', 
      description: 'Laptop - description', category: 'Computers' },
      { code: 'P002', name: 'Smartphone', 
      description: 'Smartphone - description', 
		category: 'Computers' },
      { code: 'P003', name: 'Mobile', 
      description: 'Mobile - description', category: 'Computers' },
      { code: 'P004', name: 'Angular Basics', 
      description: 'Angular Basics - description', 
		category: 'Books' },
      { code: 'P005', name: 'ng-book - The Complete Book on AngularJS', 
		description: 'ng-book - The Complete Book on AngularJS - description', 
		category: 'Books' },
      { code: 'P006', name: 'AngularJS Essentials', 
      description: 'AngularJS Essentials - description', 
		category: 'Books' }
    ];

    var factory = {};
    factory.getProducts = function () {
        return products;
    };

    factory.loadProductByCode = function (code) {
        var productFound;

        for (var i = 0; i < products.length; i++) {
            if (products[i].code == code) {
                productFound = products[i];
                break;
            }
        }

        return productFound;
    };

    factory.saveProduct = function (product) {
        var tempProduct = factory.loadProductByCode(product.code);

        if (tempProduct == null || tempProduct == undefined) {
            tempProduct = {};
            tempProduct.code = product.code;
            tempProduct.name = product.name;
            tempProduct.description = product.description;
            tempProduct.category = product.category;

            products.push(tempProduct);
        }
        else {
            tempProduct.code = product.code;
            tempProduct.name = product.name;
            tempProduct.description = product.description;
            tempProduct.category = product.category;
        }
    };

    factory.deleteProduct = function (code) {
        var tempProduct = factory.loadProductByCode(code);

        if (tempProduct != null) {

            products.remove(tempProduct);
        }
    };

    return factory;
});

We use the module's factory function in order to define factory service component. The code is self-explanatory, it contains only some helpers properties/functions. The deleteProduct function in the end of code listing is using an array function remove, which is not really a default array function, I used a custom function to add it to Array.prototype to make it accessible anywhere in the website. Make sure you do this in the beginning of the application loading, before any related code is going to be executed, for this article, I put it in the index.html script tag.

In factory components, we usually have to access data from server, but for the scope of this article, we are using only temporary in-memory array of products. Hopefully in the next article, I will change its code to access data from the server database.

Points of Interest

We are done with our CRUD example with AngularJS, I really enjoyed writing my experience I learned with Angular. I hope you also enjoyed this article and got something out of it.

I am planning to write another article, and try to use a server-side data storage and make requests to server from AngularJS. I appreciate your feedback/comments or any improvements you want to suggest in this topic, to help in making the article better and helpful for others.

History

  • 14th October 2015: Article posted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Support Services Company Ltd.
Pakistan Pakistan
Karachi - Pakistan.
http://idreesdotnet.blogspot.com/

Comments and Discussions

 
GeneralMy vote of 5 Pin
Santhakumar M17-Oct-15 18:51
professionalSanthakumar M17-Oct-15 18:51 
GeneralRe: My vote of 5 Pin
Muhammad Idrees GS17-Oct-15 22:30
Muhammad Idrees GS17-Oct-15 22:30 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun16-Oct-15 1:57
Humayun Kabir Mamun16-Oct-15 1:57 
GeneralRe: My vote of 5 Pin
Muhammad Idrees GS16-Oct-15 20:36
Muhammad Idrees GS16-Oct-15 20:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.