AngularJS Smart-Table select all rows directive
So I’ve been recently working on an app that required the ability for users to select all rows in a table, as well as selecting rows manually. I then realised that such a function had not existed yet for Smart Table Module, so I thought I’d share this with you guys.
You’ll also be able the get the data from the selected rows into a $scope
, which for some reason, is not yet implemented in Smart-Table.
Smart Table is a table module for AngularJS. It allows you to quickly compose your table in a declarative way including sorting, filtering, row selection and pagination. It’s also lightweight (around 3kb minified) and has no other dependencies than Angular itself.
Firstly, let’s start with the directives. There is one for row slection, which creates the checkbox for every row and assigns the st-selected
class and another to select all the rows, to which we pass our table data and it checks it to see which items have isSelected == true
rowSelectAll.js
function rowSelectAll() {
return {
require: '^stTable',
template: '<input type="checkbox">',
scope: {
all: '=rowSelectAll',
selected: '='
},
link: function (scope, element, attr) {
scope.isAllSelected = false;
element.bind('click', function (evt) {
scope.$apply(function () {
scope.all.forEach(function (val) {
val.isSelected = scope.isAllSelected;
});
});
});
scope.$watchCollection('selected', function(newVal) {
var s = newVal.length;
var a = scope.all.length;
if ((s == a) && s > 0 && a > 0) {
element.find('input').attr('checked', true);
scope.isAllSelected = false;
} else {
element.find('input').attr('checked', false);
scope.isAllSelected = true;
}
});
}
};
}
angular
.module('app')
.directive('rowSelectAll', rowSelectAll)
rowSelect.js
function rowSelect() {
return {
require: '^stTable',
template: '<input type="checkbox">',
scope: {
row: '=rowSelect'
},
link: function (scope, element, attr, ctrl) {
element.bind('click', function (evt) {
scope.$apply(function () {
ctrl.select(scope.row, 'multiple');
});
});
scope.$watch('row.isSelected', function (newValue) {
if (newValue === true) {
element.parent().addClass('st-selected');
element.find('input').attr('checked', true);
} else {
element.parent().removeClass('st-selected');
element.find('input').attr('checked', false);
}
});
}
};
}
angular
.module('app')
.directive('rowSelect', rowSelect)
Next, in order to get data from the selected rows, I’ve created two functions. selectAll()
goes with the rowSelectAll
directive and we pass it the entire dataset. select()
only needs the row
from ng-repeat
, being assigned to the single row selection directive.
app.js
function MainCtrl() {
var vm = this;
// Declare the array for the selected items
vm.selected = [];
// Function to get data for all selected items
vm.selectAll = function (collection) {
// if there are no items in the 'selected' array,
// push all elements to 'selected'
if (vm.selected.length === 0) {
angular.forEach(collection, function(val) {
vm.selected.push(val.id);
});
// if there are items in the 'selected' array,
// add only those that ar not
} else if (vm.selected.length > 0 && vm.selected.length != vm.data.length) {
angular.forEach(collection, function(val) {
var found = vm.selected.indexOf(val.id);
if(found == -1) vm.selected.push(val.id);
});
// Otherwise, remove all items
} else {
vm.selected = [];
}
};
// Function to get data by selecting a single row
vm.select = function(id) {
var found = vm.selected.indexOf(id);
if(found == -1) vm.selected.push(id);
else vm.selected.splice(found, 1);
}
}
angular
.module('app', ['smart-table'])
.controller('MainCtrl', MainCtrl)
The directives add the st-selected
class to every row that is selected, so in order to see the selected row, just style that class.
style.css
.st-selected > td {
background: aliceblue;
}
See it in action
And that’s it! If you have any questions, let me know in the comments below.