AngularJS – CRUD Data Grid III

The goal of this post is to extend the AngularJS CRUD Grid that we created in previous posts:

We will add now the following requirements:

  • # 1 Filter items.
  • # 2 Custom buttons: This will allow us to add button columns that will call the parent controller with the id of the button clicked and the associated item as parameter.

Results

Code is available on github: https://github.com/softwarejc/angularjs-crudgrid. Feel free to play with it, find errors and write improvements.

You can see a live demo here: AngularJS CRUD Grid III demo.

Filters:

All items

image

Items containing the letter ‘c’

image

Custom buttons:

image

Button click, callback that shows a popup:

image

Implementation

Filters

I use the AngularJS ng-repeat filter feature:

ng-repeat=”knownItem in itemsCtrl.allItems | filter:itemsCtrl.filter”

This works out of the box but I improved it using a throttle method that applies the filter after 500ms without writing, this improve the performance of our filter.

The idea is simple, we have two properties:

  • filterText: The text written on the filter input, this is not the filter applied to our items. After a change wait 500ms without more changes and then set the filter property.
  • filter: The filter applied to our items.
<!--Filter-->
<div class="input-group col-md-12 filter">
    <span class="input-group-addon">
        <i class="glyphicon glyphicon-search"></i>
    </span>
 
    <input class="form-control filter-input" type="text" ng-keydown="itemsCtrl.filterChanged()" ng-model="itemsCtrl.filterText" placeholder="filter...">
 
    <span class="input-group-addon btn btn-default" ng-click="itemsCtrl.clearFilter()" ng-hide="itemsCtrl.filter.length == 0">
        <i class="glyphicon glyphicon-remove"></i>
    </span>
</div>
function _filterChanged() {
    _filterThrottle.run(function () {
        // update filter
        $scope.$apply(function () {
            self.filter = self.filterText;
        });
    });
}

The throttle method:

(function () {
    'use strict';
 
    // module definition
    stockModule.factory("reactiveFactory"function reactiveFactory() {
        return {
            // Execute an action after a period of time without calls
            getThrottle: _createThrottle
        };
 
        function _createThrottle(delay) {
            var throttleTimer = null;
            var throttleDelay = delay;
 
            if (!throttleDelay) {
                // use default value 250ms
                throttleDelay = 250;
            }
 
            return {
                run: function(action) {
                    return function() {
                        clearTimeout(throttleTimer);
 
                        throttleTimer = setTimeout(function() {
                            // execute action
                            action.apply();
 
                            // dispose timer
                            throttleTimer = null;
                        }, throttleDelay);
                    }();
                }
            };
        }
 
    });
})();

Custom buttons

With custom buttons we want to get a call on the parent controller of our grid with the id of the button clicked and the associated item.

We need a new column type: button.

This column has this configuration:

  • icon: glyphicon to display in our button
  • buttonid: id passed to the parent when this button is clicked
  • class: class applied to the cell button

An example of a column definitions with two button type columns:

<div crud-grid
       column-button-click='itemsCtrl.gridOnButtonClick'
       initialized='itemsCtrl.gridOnInitialized'
       server-url='/api/Items'
       columns-definition='[
       {
          "binding"       :"id",
          "type"          :"text",
          "required"      :"true",
          "hidden"        :"true"
       },
       {
          "binding"       :"name",
          "header"        :"Name",
          "type"          :"text",
          "required"      :"true"
       },
       {
          "binding"       :"description",
          "header"        :"Level",
          "type"          :"text",
          "required"      :"false"
       },
       {
           "type"         :"button",
           "icon"         :"btn glyphicon glyphicon-plus",
           "buttonid"     :"plus",
           "class"        :"column-width-auto"
       },
       {
           "type"         :"button",
           "icon"         :"btn glyphicon glyphicon-minus",
           "buttonid"     :"minus",
           "class"        :"column-width-auto"
       }
       ]'>
  </div>

To get the notifications we need to add a callback to our grid:

div crud-grid column-button-click=’itemsCtrl.gridOnButtonClick’

'use strict';
(function () {
    stockModule.controller("itemsController", itemsController);
 
    function itemsController(modalWindowFactory) {
 
        var self = this;
 
        //// ---------------- PUBLIC ----------------
        //// PUBLIC fields
        self.gridController = {};
 
        //// PUBLIC Methods
        // Method executed when a button inside the grid is clicked
        self.gridOnButtonClick = _gridOnButtonClick;
 
        // Method executed when the grid is initialized
        self.gridOnInitialized = _gridOnInitialized;
 
        //// ---------------- CODE TO RUN -----------
 
        //// ---------------- PRIVATE ---------------
        //// PRIVATE fields
 
        //// PRIVATE Functions - Public Methods Implementation	
        function _gridOnInitialized(controller) {
            self.gridController = controller;
        }
 
        function _gridOnButtonClick(sender, args) {
            console.log("button click" + args.button + " " + args.item.id);
 
            if (args.button == 'plus') {
                modalWindowFactory.show(args.item.name, "Custom button click = +");
            }
            else if (args.button == 'minus') {
                modalWindowFactory.show(args.item.name, "Custom button click = -");
            }
        }
  
    };
})();

How is the grid calling the parent callback with parameters?

We do a method binding to “columnButtonClick”

UI Binding

<!-- Button -->
<span ng-switch-when="button">
 <div class="btn-group ">
 <i ng-class="column.icon" 
  ng-click="itemsCtrl.notifyColumnClick(column.buttonid, knownItem)"></i>
 </div>
</span>

Call from the directive:

function _notifyColumnClick(id, clickedItem) {
    if ($scope.columnButtonClick()) {
        $scope.columnButtonClick()(this, { button: id, item: clickedItem });
    }
}

Please leave a comment!

7 thoughts on “AngularJS – CRUD Data Grid III

  1. Pingback: AngularJS – CRUD Data Grid I | Juan Carlos Sanchez's Blog

    • Hi, paging can be implemented for this grid, you can make a pull request and do it by yourself if you want. I think it would be a nice feature…

      I can also implement it, but I don’t know when, I am a little busy now…

      Thank you for your comment!

      Like

Your feedback is important...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.