Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

AngularJS Backend Solution: ng-grid with a Simple REST API

5.00/5 (6 votes)
8 Oct 2014CPOL6 min read 73.9K  
Filter, sort and paging with ng-grid using AngularJS and REST

Introduction

It is a common requirement for any project to display data in some kind of tabular format. The easiest way to achieve this is by using HTML table. But soon, this gets complex as you need a way to support pagination (client-side and server-side), sorting (single & multi column), resizable columns, inline editing, filtering, etc. What the article/code snippet does, why it's useful, the problem it solves, etc.

Using the Code

First Grid Solution

The first solution we are going to look at is ng-grid which is built for AngularJS and is the most popular Grid solution out there for Angular.

Where to Start

In this project, we will build a grid solution using Angular and ng-grid, which hooks in to the RESTful end point running locally using NodeJS & ExpressJS. We will use basic features of Node & Express. Before jumping in, you may want to see the working code on Plunker: http://embed.plnkr.co.

Assumptions

  1. You already know AngularJS
  2. Know the basics of Grunt, Bower and Bootstrap
  3. Have basic knowledge about REST
  4. You already have node, npm, git and bower installed on your development machine

Project Structure

We will use the following Angular seed project:
https://github.com/libertyleap/angular-grunt-seed

This is the seed project which comes with a default bower and grunt build for lint, karma, watch, livereload, express server, etc.

Steps to Setup & Run Seed Project

  1. Clone the project:

    > git clone https://github.com/backand/ng-grid-rest-simple-demo

  2. Rename the project from angular-grunt-seed to ng-grid-demo:

    > mv angular-grunt-seed ng-grid-demo

  3. Change the current directory to ng-grid-demo:

    > cd ng-grid-demo

  4. Execute npm install so that all the Grunt dependencies are downloaded and it also runs bower install:

    > npm install

  5. Execute grunt, this will start the local Node server on port 9000:

    > grunt

  6. Open your favorite browser and go to: http://localhost:9000/:

    Image 1

Adding NG-Grid into Seed Project Using Bower

The easiest way to add ng-grid to seed project is using Bower and we will cover this approach in this blog. If you are not comfortable doing this, you can do it manually, i.e., go to ng-grid repo: http://angular-ui.github.io/ng-grid/ and copy over the required files which are covered below.

> bower install ng-grid –save-dev

Above command updates the ng-grid-demo\bower.json file to add ng-grid as dependency.

JavaScript
"devDependencies": {

    "ng-grid": "~2.0.12"
}

Bower will download ng-grid locally. You can verify this by going in to the bower-components folder. You will see a new folder ng-grid inside the bower-components folder.

Image 2

Hooking-up NG-Grid with View Restful Service

To utilize ng-grid in our seed project, we need to reference two ng-grid files. The first one is the JavaScript file and the second is the CSS for the theming of the grid. The first step will be to go into your index.html file and add both the JavaScript and the CSS files as dependency.

Open the ng-grid-demo/src/index.html file and add the following entries:

  1. In the <head>, add this CSS dependency (bower-components/ng-grid/ng-grid.css).

    Image 3

  2. In the <body> section, add ng-grid’s js dependency (bower-components/ng-grid/ng-grid-2.0.12.debug.js).
  3. We need to add the 'ngGrid' Angular module dependency to app.js so that we can start using ng-grid’s directives and other services.

    Image 4

NG-Grid Basic Example

We will look at the steps required to add the basic ng-grid example in this section. We will explore ng-grid’s advanced features in the coming sections.

To be able to demonstrate grid features, we need some kind of REST endpoint. For this blog post, we will use local JSON file as REST endpoint, which will serve list of open source contributors.

REST \ JSON

Create a folder json under ng-grid-demo\src folder. Create a new json file called contributors.json. This JSON file will have the following content, which will be served to UI \ ng-grid.

ng-grid-demo\src\json\contributor.json
JavaScript
[{
    "id": "1",
    "firstname": "Misko",
    "lastname": "Havery",
    "company": "Google",
    "project": "AngularJS"
}, {
    "id": "2",
    "firstname": "Srini",
    "lastname": "Kusunam",
    "company": "LibertyLeap",
    "project": "Backbone.Paginator"
}, {
    "id": "3",
    "firstname": "Derick",
    "lastname": "Bailey",
    "company": "Muted Solutions",
    "project": "Backbone.Marionette"
}]

Change the Grunt build to include this json file in .build directory.

Angular Factory

Let’s create a service (gridService.js) that will return the above JSON using REST’s GET method. This data will be returned asynchronously and we will use Promises ($q) for this. Here is the Service code.

JavaScript
angular.module('angularGruntSeed')
    .factory('GridService', ['$http', '$q',
        function($http, $q) {
            var contributorsFile = 'json/contributors.json';
            var contributors = [];
 
            function getContributors() {
                var deferred = $q.defer();
 
                $http.get(contributorsFile)
                    .then(function(result) {
                        contributors = result.data;
                        deferred.resolve(contributors);
                    }, function(error) {
                        deferred.reject(error);
                    });
 
                return deferred.promise;
            }

            return {
                getContributors: getContributors
            };
        }
    ]);

We will have one method called getContributors which will use Angular’s $http (https://docs.angularjs.org/api/ng/service/$http) to get the data from json/contributors.json file. It also uses Angular’s promise implementation $q (https://docs.angularjs.org/api/ng/service/$q).

This is what is happening here:

  • When controller calls this factory method “getContributors”, it will get a promise object back i.e., deferred.promise.
  • When response comes back from the asynchronous $http call, we will resolve deferred object to return list of contributors.
  • If there is an error in $http, then we will reject the deferred object with the reason so that caller can handle it appropriately, i.e., show some kind of message back to user.

Controller

We will add “GridService” as a dependency to “HomeController” and call “getContributors” method from GridService. Response is set as “myData” which will be used to populate ng-grid data in view.

JavaScript
angular.module('angularGruntSeed')
.controller('HomeController', ['$scope', 'GridService',
    function($scope, gridService) {
         gridService.getContributors().then(function(data) {
            $scope.myData = data;
        });
 
        $scope.gridOptions = {
            data: 'myData'
        };
    }
]);

The above step $scope.gridOptions is the main setup which hooks-up ng-grid configuration to ng-grid’s view.

View

Setting up the grid in your HTML file is really easy and just requires creating a div, and adding a ng-grid directive to it with the parameter being the function in the controller that we will create soon. We are also going to add a simple class onto the div for easy styling. Change “templates\home.html” to include the following code:

JavaScript
<div class="gridStyle" ng-grid="gridOptions"></div> 

Here, “gridOptions” is $scope object populated in controller.

This should get the basic ng-grid up and running.

Image 5

NG-Grid Features

In this section, we will explore different configuration options for ng-grid. We just need to change $scope.gridOptions in Controller to be able to support the following features.

Column Definition

It is a common requirement for any Grid to name column names different from the JSON name. One example above is we want to name “firstname” to “First Name”.

JavaScript
$scope.gridOptions = {
    data: 'myData',
    // Column definition example
    columnDefs: [{field:'id'},{field:'firstname', displayName:'First Name'},     
                 {field:'lastname',displayName:'LastName'},{field:'company'},{field:'project'}]
};

Cell Template Example

Below is an example on how to define cell templates using strings in ng-grid. From the above example, we want to apply Green color to id column with id > 1.

JavaScript
$scope.gridOptions = {
    data: 'myData',
    columnDefs: [
{field:'id', cellTemplate: '
<div ng-class="{green: row.getProperty(col.field) > 1}">
			<div class="ngCellText">{{row.getProperty(col.field)}}</div>
			</div>
'}, {field:'firstname', displayName:'First Name'}, 
{field:'lastname', displayName:'Last Name'}, 
{field:'company'},{field:'project'}] };

In-line Cell Editing Example

We will explore an option to be able to edit the Grid cell and save it to the REST service. We will demonstrate code to be able to update the “company” cell of the contributor in Grid.

homeController.js

We need to set enableCellEdit property to TRUE for the column definition.

JavaScript
{
    field:'company',
    enableCellEdit: true
}

After setting this, if you restart the node server, you will see company column is editable after double clicking the cell.

Image 6

The next step is we want to send this updated cell info to REST backend. For this, we will use one of ng-grid’s Event (ngGridEventEndCellEdit), which will broadcast after cell is edited. You can see all the available ng-grid’s Events here: https://github.com/angular-ui/ng-grid/wiki/Grid-Events.

We will update the controller to have the following code:

JavaScript
$scope.$on('ngGridEventEndCellEdit', function(evt){
   // Detect changes and send entity to REST server
   gridService.saveContributor(evt.targetScope.row.entity);
});

As you can see from the above code, we want to send the updated row information back to REST service. We need to define a new method saveContributor in our gridService.js.

gridService.js

JavaScript
function saveContributor(contributor) {
    $http.post('/save', contributor).success(function() {
    console.log("SAVE success !!!!");
    }).error(function() {
    console.log("SAVE Error !!!!");
    });
}

We do not have a real REST service and it is impossible to demo this as we need some kind of persistent store. You can open your browser’s developer tools and validate the above $http post method is called with the right data.

References

License

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