Grouping data in NG-Grid

The NG-Grid is quite feature-rich, and besides the regular column sorting and alternating rows, it also allows for features such as the grouping of data by a column and Excel-style inline editing.

Let’s see how data grouping in NG-Grid works. For this to look better and work more efficiently let’s create a new attribute called Subscription Type in our models and use it for grouping.

Let’s add a new property to our subscribers list in our subscribers.json file as highlighted in the following lines of code:

[
{"no":"1", "name":"Betty", "loyalty": 3,"joinDate":"3/5/10", "userType":"Free"},
{"no":"2", "name":"John", "loyalty": 5,"joinDate":"3/5/05", "userType":"Premium"},
{"no":"3", "name":"Peter", "loyalty": 6,"joinDate":"3/5/10", "userType":"Free"},
{"no":"4", "name":"Jaden", "loyalty": 7,"joinDate":"10/12/12", "userType":"Premium"},
{"no":"5", "name":"Shannon", "loyalty": 9,"joinDate":"22/01/08", "userType":"Premium"}
]

We’ll also add it to the column definitions in the gridOptions settings.

$scope.gridOptions = { 
    data: 'subscribers',
        columnDefs: [
        {field:'no', displayName:'No.'}, 
        {field:'name', displayName:'Name'}, 
        {field:'userType', displayName:'Subscription Type'}, 
        {field:'loyalty', displayName:'Loyalty Score'},
        {field:'joinDate', displayName:'Date of Joining'}]

};

Save the file and verify that the Subscription Type column is now visible on the Subscriptions view.

Now, we’d like the user to drag a column into the group area and group the rows based on the selected column, something like the data-filters feature in the Excel Pivot tables.

Enabling this in NG-Grid is very simple; you simply need to add the following parameter to gridOptions in app/scripts/controllers/subscribers.js as highlighted in the following lines of code:

$scope.gridOptions = { 
    data: 'subscribers',
    showGroupPanel: true,
    columnDefs: [
        {field:'no', displayName:'No.'}, 
        {field:'name', displayName:'Name'}, 
        {field:'userType', displayName:'Subscription Type'}, 
        {field:'loyalty', displayName:'Loyalty Score'},
        {field:'joinDate', displayName:'Date of Joining'}]

};

Save the file and refresh the Subscriptions view in your browser. You should now see a new area above the column headings. Drag the Subscription Type column heading and drop it in the area above it.

Note that the data in your grid has been grouped on the basis of the subscription type, and it also tells you the total number of users within each group. This is demonstrated in the following screenshot:

Grouping data in NG-Grid

Excel-style editing in NG-Grid

I’m sure many of you come across this requirement where you need to allow for inline editing within a data grid. Trying to do this using the regular jQuery and Ajax can be quite an effort. Now, with NG-Grid, it’s just about enabling these settings within gridOptions.

Open the app/scripts/controllers/subscribers.js file and add the following highlighted parameter to gridOptions:

$scope.gridOptions = { 
    data: 'subscribers',
    showGroupPanel: true,
    jqueryUIDraggable: true,
    enableCellSelection: true,
    enableRowSelection: false,
    enableCellEdit: true,
   columnDefs: [
        {field:'no', displayName:'No.'}, 
        {field:'name', displayName:'Name'}, 
        {field:'userType', displayName:'Subscription Type'}, 
        {field:'loyalty', displayName:'Loyalty Score'},
        {field:'joinDate', displayName:'Date of Joining'}]

};

Save the file, and in the Subscriptions view in the browser, try double-clicking on any one of the cells, change the text, and press Enter. As simple as that! The following screenshot is the output obtained:

Excel-style editing in NG-Grid

Creating a modal window to add subscribers

Now that we have a feature-rich data grid displaying our subscribers, let’s create a modal window with a form to add users to our subscribers model.

Adding a modal window using Angular UI is a little more complicated than the rest of the components we have seen until now.

To start with, we will need a button that will launch the modal window when it is clicked on.

We will create this button in the app/views/subscribers.html file with the following highlighted lines of code:

<h1>Subscribers</h1>
<button class="btn btn-success" ng-click="showModal()"> Add New User</button>   
<div class="gridStyles" ng-grid="gridOptions">
</div>

The .btn class sets the button’s basic styles such as rounded corners, font size, padding, and so on. The .btn-success class gives it the green color. In the ng-click directive, we are calling a function named showModal.

We will now create the partial for the modal view. Create a new file called add-user.html within the app/views folder, and let’s put in the markup for the Add New User form as follows:

<div class="modal-header">
   <button type="button" class="close" ng-click="cancel()" data-dismiss="modal" aria-hidden="true">&times;</button>
   <h1>Add a Subscriber</h1>
</div>

We define the heading for the modal window by applying the .modal-header class.

We also place our close button within the header.

Next, we will mark up the content for the modal body.

<div class="modal-body"> 
<label>Name</label><input type="text" ng-model="newUser.name"/>
<label>Subscription Type</label><input type="text" ng-model="newUser.userType"/>
<label>Loyalty Score</label><input type="number" ng-model="newUser.loyalty"/>
<label>Date of Joining</label><input type="date" ng-model="newUser.joinDate"/>
<br/>
<button class="btn btn-success" ng-click="saveNewUser()"> Save User</button>

</div>

The code is straightforward; we wrap our form elements within a <div> with the .modal-body class.

We have four form elements, which are tied to the respective properties of the newUser object.

The Add New User button, when clicked on, will call the AddNewUser function.

Note

Note the type attributes for each of the input elements. These type attributes are automatically used by modern browsers for validations. angularjs too appends its own CSS class to enable real-time validation notifications.

Next, we will add the code to our app/scripts/controllers/subscribers.js file.

The modal window makes use of the $modal service, so we will need to add it to SubscribersCtrl as highlighted in the following lines of code:

angular.module('hlApp')
  .controller('SubscribersCtrl', function ($scope,$http, $modal) {

Next, we will write the code to call the modal window.

As the Add New User button function will call the showModal function when clicked on, we will define that function at the end, just above the closing braces of our SubscribersCtrl controller as follows:

$scope.showModal=function () {
$scope.newUser={};
    var modalInstance = $modal.open({
      templateUrl: 'views/add-user.html'})}

The $modal service has a method named open(), with a couple of options, templateUrl being one of them.

We are also creating an empty model object named newUser. We will be using this to store the form data from the modal window.

Save the file and test it in the browser. Clicking on the Add New User Button should slide the modal window into view. However, this is quite static, and neither the close button nor the Save User buttons will work because we haven’t yet coded in the saveNewUser() or cancel() functions.

An important thing to note is that the $modal service will create its own scope within the parent scope.

Another option that the $modal.open method supports is the controller that allows you to assign another controller, that binds to the view within the modal. Let us now add the controller option to modalInstance.

$scope.showModal= function () {
    var modalInstance = $modal.open({
      templateUrl: 'views/add-user.html',
      controller:'AddNewUserCtrl'

    })}

Next, we’ll create AddNewUserCtrl within the same app/scripts/controllers/subscribers.js file.

We add this controller right at the end of the file after the SubscribersCtrl function ends as follows:

.controller('AddNewUserCtrl', function ($scope, $modalInstance) {
});

Tip

Don’t forget to remove the semicolon at the end of the SubscribersCtrl function.

Now, within AddNewUserCtrl, we’ll define the functions for the Cancel button as follows:

 .controller('AddNewUserCtrl', function ($scope, $modalInstance) {
  $scope.cancel =function(){
    $modalInstance.dismiss('cancel');
  };
});

Save the files and check to see if the Add New User and the Cancel buttons are working. Add the following CSS class to get your form to look aligned:

.modal-body input{
display:block;
}

You should be seeing something like the following screenshot:

Creating a modal window to add subscribers Now, let’s add the rest of the code to save the user.In the AddNewUserCtrl controller, add the following highlighted code:

.controller('AddNewUserCtrl', function ($scope, $modalInstance,newUser) {
$scope.newUser=newUser;
$scope.saveNewUser=function(){
  $modalInstance.close(newUser);
};

  $scope.cancel =function(){
    $modalInstance.dismiss('cancel');
  }

});

We’ll now add the last option to our $modal.open method, which is named resolve. The code is highlighted as shown in the following lines of code:

var modalInstance = $modal.open({
templateUrl: 'views/add-user.html',
controller: 'AddUserCtrl',
resolve: {
   newUser: function () {
   return $scope.newUser;
        }
      }
    });

Like most services, $modal also makes use of promises to return the objects and variables that have been asked for.

Here, in the resolve part, we are returning the newUser model object.

Now that we have the newUser model returned to us as a response to the promise, we need push the data from it into our subscribers model. This is done by the following piece of code:

modalInstance.result.then(function (selectedItem) {
$scope.subscribers.push({
no:$scope.subscribers.length+1,
name:$scope.newUser.name,
userType:$scope.newUser.userType,
loyalty:$scope.newUser.loyalty,
joinDate:$scope.newUser.joinDate

  });
});

Notice that for the no column, I’m simply taking the length of our current model and incrementing it by 1.

Also note that the preceding code is written within the showModal function.

The complete code for showModal should be as follows:

$scope.showModal=function () {
   $scope.newUser={};
    var modalInstance = $modal.open({
      templateUrl: 'views/add-user.html',
      controller:'AddNewUserCtrl',
      resolve: {
         newUser: function () {
        return $scope.newUser;
        }
      }


    })

    modalInstance.result.then(function (selectedItem) {
    $scope.subscribers.push({
    no:$scope.subscribers.length+1,
    name:$scope.newUser.name,
    userType:$scope.newUser.userType,
    loyalty:$scope.newUser.loyalty,
    joinDate:$scope.newUser.joinDate

      });
    });

  }