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
Items containing the letter ‘c’
Custom buttons:
Button click, callback that shows a popup:
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 }); } }
Pingback: AngularJS – CRUD Data Grid I | Juan Carlos Sanchez's Blog
How can i add Paging in ur table? i would use it in production if it could have paging!
LikeLike
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!
LikeLike
Hello, Mr Juan Carlos
It is a list as your data source of your project.
Have you a project works with databases?
Thanks
LikeLike
If you have a database implement a service around it and everything should work. Regards
LikeLike
If you have a good sample project, please send it by email.
LikeLike
Hello, Mr. Juan Carlos Sanchez
Have you work a project in master/detail template?
Thanks
LikeLike