From 3dff3cb4506c15de4f297651f099f3ee744e87ec Mon Sep 17 00:00:00 2001 From: EugenDraytsev Date: Wed, 20 Jan 2016 07:18:56 +0300 Subject: [PATCH 1/2] Fixed select bug, some encapsulation improvements. --- demo/100k/css/angular-data-grid.bootstrap.css | 26 +++ demo/100k/index.html | 217 ++++++++++++++++++ demo/100k/js/demoApp.js | 34 +++ .../scss/angular-data-grid.bootstrap.scss | 32 +++ dist/dataGrid.js | 35 ++- dist/dataGrid.min.js | 2 +- src/js/dataGrid.js | 35 ++- 7 files changed, 368 insertions(+), 13 deletions(-) create mode 100644 demo/100k/css/angular-data-grid.bootstrap.css create mode 100644 demo/100k/index.html create mode 100644 demo/100k/js/demoApp.js create mode 100644 demo/100k/scss/angular-data-grid.bootstrap.scss diff --git a/demo/100k/css/angular-data-grid.bootstrap.css b/demo/100k/css/angular-data-grid.bootstrap.css new file mode 100644 index 0000000..2d4f7b2 --- /dev/null +++ b/demo/100k/css/angular-data-grid.bootstrap.css @@ -0,0 +1,26 @@ +.table > thead > tr > th { + vertical-align: middle; } + +.p-t-8 { + padding-top: 8px; } + +.margin-bottom-basic { + margin-bottom: 15px; } + +.pagination { + margin: 0; } + +.items-per-page { + margin-left: 15px; } + +.sortable:after { + font: 14px/1 FontAwesome; + content: "\f0dc"; } + +.sortable.sort-ascent:after { + content: '\f0de'; + vertical-align: bottom; } + +.sortable.sort-descent:after { + content: "\f0dd"; + vertical-align: top; } diff --git a/demo/100k/index.html b/demo/100k/index.html new file mode 100644 index 0000000..a4456d8 --- /dev/null +++ b/demo/100k/index.html @@ -0,0 +1,217 @@ + + + + + Angular Data Grid - Bootstrap Design + + + + + + + +
+
+

Angular Data Grid 100k Example

+ Features enabled: sorting, filtering (using both in-grid and external controls), sync with browser URLs, + pagination and items-per-page functionality. + Angular UI Datepicker used for date controls, although you can use any other framework, plugin or styling. + Project GitHub +
+
+
+
+
+
+ + +
+
+
+
+ + +
+ + + + +
+
+
+
+
+ + +
+ + + + +
+
+ +
+
+
+
+
+
+
+
+
+ {{filtered.length}} users total +
Time stats
+
Copy time: {{_time.copy}}
+
Filter time: {{_time.filters}}
+
Sort time: {{_time.sort}}
+
All time: {{_time.all}}
+
+
+
+
+ +
+
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ User Id + + Name + + Phone + + Date Of Birth +
+
+
+ +
+
+ + +
+
+
+
+
+
+
+ +
+

See the Pen xZddZm by AngularDataGrid (@AngularDataGrid) on CodePen. +

+ +
+
+
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/demo/100k/js/demoApp.js b/demo/100k/js/demoApp.js new file mode 100644 index 0000000..082b997 --- /dev/null +++ b/demo/100k/js/demoApp.js @@ -0,0 +1,34 @@ +(function () { + 'use strict'; + + angular.module('myApp', ['ui.bootstrap', 'dataGrid', 'pagination']) + .controller('myAppController', ['$scope', function ($scope) { + + $scope.gridOptions = { + data: generateJSON(100000), + urlSync: true + }; + + }]); + + function generateJSON(length) { + var jsonObj = [], + i, + max, + names = ['Ann', 'Ben', 'Patrick', 'Steve', 'Fillip', 'Bob'], + item; + for (i = 0, max = length; i < max; i++) { + + item = {}; + item.id = i; + item.name = names[Math.round(Math.random() * (names.length - 1))]; + item.phone = '+375-29-' + Math.round(Math.random() * 1000000); + item.date = Math.round(Math.random() * 1000000000000); + jsonObj.push(item); + + } + return jsonObj; + } +})(); + + diff --git a/demo/100k/scss/angular-data-grid.bootstrap.scss b/demo/100k/scss/angular-data-grid.bootstrap.scss new file mode 100644 index 0000000..4699ed7 --- /dev/null +++ b/demo/100k/scss/angular-data-grid.bootstrap.scss @@ -0,0 +1,32 @@ +.table > thead > tr > th { + vertical-align: middle; +} +.p-t-8 { + padding-top: 8px; +} +.margin-bottom-basic { + margin-bottom: 15px; +} + +.pagination { + margin: 0; +} + +.items-per-page { + margin-left: 15px; +} + +.sortable { + &:after { + font: 14px/1 FontAwesome; + content: "\f0dc"; + } + &.sort-ascent:after { + content: '\f0de'; + vertical-align: bottom; + } + &.sort-descent:after { + content: "\f0dd"; + vertical-align: top; + } +} \ No newline at end of file diff --git a/dist/dataGrid.js b/dist/dataGrid.js index a265408..4e8fba8 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -215,12 +215,35 @@ } function applyFilters() { - $scope.filtered = angular.copy($scope._gridOptions.data); + var time = Date.now(), sorted = false; - applyCustomFilters(); + //TO REMOVE ? + $scope._time = {}; + + if ($scope.sortOptions.predicate && $scope.sortCache && $scope.sortCache.predicate === $scope.sortOptions.predicate + && $scope.sortCache.direction === $scope.sortOptions.direction) { + $scope.filtered = $scope.sortCache.data.slice(); + sorted = true; + } else { + $scope.filtered = $scope._gridOptions.data.slice(); + } - //apply orderBy filter - $scope.filtered = $filter('orderBy')($scope.filtered, $scope.sortOptions.predicate, $scope.sortOptions.direction === 'desc'); + $scope._time.copy = Date.now() - time; + var time2 = Date.now(); + applyCustomFilters(); + $scope._time.filters = Date.now() - time2; + var time3 = Date.now(); + + if ($scope.sortOptions.predicate && !sorted) { + $scope.filtered = $filter('orderBy')($scope.filtered, $scope.sortOptions.predicate, $scope.sortOptions.direction === 'desc'); + $scope.sortCache = { + data: $scope.filtered.slice(), + predicate: $scope.sortOptions.predicate, + direction: $scope.sortOptions.direction + } + } + $scope._time.sort = Date.now() - time3; + $scope._time.all = Date.now() - time; $scope.paginationOptions.totalItems = $scope.filtered.length; } @@ -316,7 +339,7 @@ if (serverPagination) { element.attr('ng-repeat', "item in filtered"); } else { - element.attr('ng-repeat', "item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage"); + element.attr('ng-repeat', "item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"); } $compile(element)(childScope); }); @@ -336,7 +359,7 @@ function textFilter(items, value, predicate) { return items.filter(function (item) { - return value && item[predicate] ? ~item[predicate].toLowerCase().indexOf(value.toLowerCase()) : true; + return value && item[predicate] ? ~(item[predicate] + '').toLowerCase().indexOf(value.toLowerCase()) : true; }); } diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index f7059c5..c1744f9 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i,r=e.split("."),n=t;for(i=0;ii.filtered.length?i.paginationOptions.currentPage=1:i.paginationOptions.currentPage=e.page),e.sort){var n=e.sort.split("-");i.sortOptions.predicate=decodeURIComponent(n[0]),i.sortOptions.direction=decodeURIComponent(n[1])}i.serverPagination||g()}function c(){var t=a.path().slice(1);i._gridOptions.getData("?"+t,function(t,e){i.filtered=t,i.paginationOptions.totalItems=e})}function g(){i.filtered=angular.copy(i._gridOptions.data),p(),i.filtered=n("orderBy")(i.filtered,i.sortOptions.predicate,"desc"===i.sortOptions.direction),i.paginationOptions.totalItems=i.filtered.length}function p(){i.filters.forEach(function(t){var e=t.filterBy,r=t.model,n=i[r],a=t.filterType;if(i.customFilters[r])i.filtered=i.customFilters[r](i.filtered,n,e);else if(n&&a){var s=o.getFilterByType(a);s&&(i.filtered=s(i.filtered,n,e))}})}i._gridOptions=t(i,r.attr("grid-options")),i._gridActions=t(i,r.attr("grid-actions")),i.serverPagination="true"===r.attr("server-pagination"),i.getDataDelay=r.attr("get-delay")||350,i._gridActions||(i.$parent[r.attr("grid-actions")]={},i._gridActions=i.$parent[r.attr("grid-actions")]),i.filtered=angular.copy(i._gridOptions.data),i.paginationOptions=i._gridOptions.pagination?angular.copy(i._gridOptions.pagination):{},i.defaultsPaginationOptions={itemsPerPage:i.paginationOptions.itemsPerPage||"10",currentPage:i.paginationOptions.currentPage||1},i.paginationOptions=angular.copy(i.defaultsPaginationOptions),i.sortOptions=i._gridOptions.sort?angular.copy(i._gridOptions.sort):{},i.customFilters=i._gridOptions.customFilters?angular.copy(i._gridOptions.customFilters):{},i.urlSync=i._gridOptions.urlSync,i.$watch("_gridOptions.data",function(t){t&&t.length&&(i.filtered=angular.copy(i._gridOptions.data),i.filters.forEach(function(t){"select"===t.filterType&&(i[t.model+"Options"]=e(i.filtered,t.filterBy))}),i.urlSync?l(a.path()):g())}),i.sort=function(t){var e=i.sortOptions.predicate===t&&"desc"===i.sortOptions.direction?"asc":"desc";i.sortOptions.predicate=t,i.sortOptions.direction=e,i.paginationOptions.currentPage=1,i.reloadGrid()},i.filter=function(){i.paginationOptions.currentPage=1,i.reloadGrid()},i.$on("$locationChangeSuccess",function(){(i.urlSync||i.serverPagination)&&(i.serverPagination&&(clearTimeout(i.getDataTimeout),i.getDataTimeout=setTimeout(c,i.getDataDelay)),i.filtered&&l(a.path()))}),i.reloadGrid=function(){i.urlSync||i.serverPagination?s():g()},i._gridActions.refresh=i.reloadGrid,i._gridActions.filter=i.filter,i._gridActions.sort=i.sort}]).directive("gridData",["$compile","$animate",function(i,r){return{restrict:"EA",transclude:!0,replace:!0,controller:"gridController",link:function(n,a,o,s,l){var c=[],g=[],p=[],u=n.$new(),d=a.parent(),f=o.id,m="true"===o.serverPagination;l(n,function(t){r.enter(t,a)}),angular.forEach(angular.element(d[0].querySelectorAll("[sortable]")),function(t){var e=angular.element(t),r=e.attr("sortable");c.push(e),e.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+r+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+r+"' && sortOptions.direction === 'desc'}"),e.attr("ng-click","sort('"+r+"')"),i(e)(u)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(r){var o=angular.element(r),s=d.find(o).length>0,l=o.attr("filter-by"),c=o.attr("filter-type")||"",p=o.attr("ng-model"),u=o.attr("disable-url");f&&o.attr("grid-id")&&f!=o.attr("grid-id")||("select"!==c||(n[p+"Options"]=e(t(n,a.attr("grid-options")+".data"),l)),!~c.indexOf("date")||o.attr("ng-focus")||o.attr("ng-blur")||(o.attr("ng-focus","filter('{"+p+" : this."+p+"}')"),o.attr("ng-blur","filter('{"+p+" : this."+p+"}')"),i(o)(n)),p||(p=l,o.attr("ng-model",l),o.attr("ng-change","filter()"),i(o)(n)),g.push({model:p,isInScope:s,filterBy:l,filterType:c,disableUrl:u}))}),angular.forEach(angular.element(d[0].querySelectorAll("[grid-item]")),function(t){var e=angular.element(t);p.push(e),m?e.attr("ng-repeat","item in filtered"):e.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage"),i(e)(u)}),n.sorting=c,n.rows=p,n.filters=g}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~t[i].toLowerCase().indexOf(e.toLowerCase()):!0})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i,r=e.split("."),n=t;for(i=0;ii.filtered.length?i.paginationOptions.currentPage=1:i.paginationOptions.currentPage=e.page),e.sort){var n=e.sort.split("-");i.sortOptions.predicate=decodeURIComponent(n[0]),i.sortOptions.direction=decodeURIComponent(n[1])}i.serverPagination||p()}function l(){var t=a.path().slice(1);i._gridOptions.getData("?"+t,function(t,e){i.filtered=t,i.paginationOptions.totalItems=e})}function p(){var t=Date.now(),e=!1;i._time={},i.sortOptions.predicate&&i.sortCache&&i.sortCache.predicate===i.sortOptions.predicate&&i.sortCache.direction===i.sortOptions.direction?(i.filtered=i.sortCache.data.slice(),e=!0):i.filtered=i._gridOptions.data.slice(),i._time.copy=Date.now()-t;var r=Date.now();g(),i._time.filters=Date.now()-r;var a=Date.now();i.sortOptions.predicate&&!e&&(i.filtered=n("orderBy")(i.filtered,i.sortOptions.predicate,"desc"===i.sortOptions.direction),i.sortCache={data:i.filtered.slice(),predicate:i.sortOptions.predicate,direction:i.sortOptions.direction}),i._time.sort=Date.now()-a,i._time.all=Date.now()-t,i.paginationOptions.totalItems=i.filtered.length}function g(){i.filters.forEach(function(t){var e=t.filterBy,r=t.model,n=i[r],a=t.filterType;if(i.customFilters[r])i.filtered=i.customFilters[r](i.filtered,n,e);else if(n&&a){var s=o.getFilterByType(a);s&&(i.filtered=s(i.filtered,n,e))}})}i._gridOptions=t(i,r.attr("grid-options")),i._gridActions=t(i,r.attr("grid-actions")),i.serverPagination="true"===r.attr("server-pagination"),i.getDataDelay=r.attr("get-delay")||350,i._gridActions||(i.$parent[r.attr("grid-actions")]={},i._gridActions=i.$parent[r.attr("grid-actions")]),i.filtered=angular.copy(i._gridOptions.data),i.paginationOptions=i._gridOptions.pagination?angular.copy(i._gridOptions.pagination):{},i.defaultsPaginationOptions={itemsPerPage:i.paginationOptions.itemsPerPage||"10",currentPage:i.paginationOptions.currentPage||1},i.paginationOptions=angular.copy(i.defaultsPaginationOptions),i.sortOptions=i._gridOptions.sort?angular.copy(i._gridOptions.sort):{},i.customFilters=i._gridOptions.customFilters?angular.copy(i._gridOptions.customFilters):{},i.urlSync=i._gridOptions.urlSync,i.$watch("_gridOptions.data",function(t){t&&t.length&&(i.filtered=angular.copy(i._gridOptions.data),i.filters.forEach(function(t){"select"===t.filterType&&(i[t.model+"Options"]=e(i.filtered,t.filterBy))}),i.urlSync?c(a.path()):p())}),i.sort=function(t){var e=i.sortOptions.predicate===t&&"desc"===i.sortOptions.direction?"asc":"desc";i.sortOptions.predicate=t,i.sortOptions.direction=e,i.paginationOptions.currentPage=1,i.reloadGrid()},i.filter=function(){i.paginationOptions.currentPage=1,i.reloadGrid()},i.$on("$locationChangeSuccess",function(){(i.urlSync||i.serverPagination)&&(i.serverPagination&&(clearTimeout(i.getDataTimeout),i.getDataTimeout=setTimeout(l,i.getDataDelay)),i.filtered&&c(a.path()))}),i.reloadGrid=function(){i.urlSync||i.serverPagination?s():p()},i._gridActions.refresh=i.reloadGrid,i._gridActions.filter=i.filter,i._gridActions.sort=i.sort}]).directive("gridData",["$compile","$animate",function(i,r){return{restrict:"EA",transclude:!0,replace:!0,controller:"gridController",link:function(n,a,o,s,c){var l=[],p=[],g=[],d=n.$new(),u=a.parent(),f=o.id,m="true"===o.serverPagination;c(n,function(t){r.enter(t,a)}),angular.forEach(angular.element(u[0].querySelectorAll("[sortable]")),function(t){var e=angular.element(t),r=e.attr("sortable");l.push(e),e.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+r+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+r+"' && sortOptions.direction === 'desc'}"),e.attr("ng-click","sort('"+r+"')"),i(e)(d)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(r){var o=angular.element(r),s=u.find(o).length>0,c=o.attr("filter-by"),l=o.attr("filter-type")||"",g=o.attr("ng-model"),d=o.attr("disable-url");f&&o.attr("grid-id")&&f!=o.attr("grid-id")||("select"!==l||(n[g+"Options"]=e(t(n,a.attr("grid-options")+".data"),c)),!~l.indexOf("date")||o.attr("ng-focus")||o.attr("ng-blur")||(o.attr("ng-focus","filter('{"+g+" : this."+g+"}')"),o.attr("ng-blur","filter('{"+g+" : this."+g+"}')"),i(o)(n)),g||(g=c,o.attr("ng-model",c),o.attr("ng-change","filter()"),i(o)(n)),p.push({model:g,isInScope:s,filterBy:c,filterType:l,disableUrl:d}))}),angular.forEach(angular.element(u[0].querySelectorAll("[grid-item]")),function(t){var e=angular.element(t);g.push(e),m?e.attr("ng-repeat","item in filtered"):e.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),i(e)(d)}),n.sorting=l,n.rows=g,n.filters=p}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf(e.toLowerCase()):!0})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index a265408..4e8fba8 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -215,12 +215,35 @@ } function applyFilters() { - $scope.filtered = angular.copy($scope._gridOptions.data); + var time = Date.now(), sorted = false; - applyCustomFilters(); + //TO REMOVE ? + $scope._time = {}; + + if ($scope.sortOptions.predicate && $scope.sortCache && $scope.sortCache.predicate === $scope.sortOptions.predicate + && $scope.sortCache.direction === $scope.sortOptions.direction) { + $scope.filtered = $scope.sortCache.data.slice(); + sorted = true; + } else { + $scope.filtered = $scope._gridOptions.data.slice(); + } - //apply orderBy filter - $scope.filtered = $filter('orderBy')($scope.filtered, $scope.sortOptions.predicate, $scope.sortOptions.direction === 'desc'); + $scope._time.copy = Date.now() - time; + var time2 = Date.now(); + applyCustomFilters(); + $scope._time.filters = Date.now() - time2; + var time3 = Date.now(); + + if ($scope.sortOptions.predicate && !sorted) { + $scope.filtered = $filter('orderBy')($scope.filtered, $scope.sortOptions.predicate, $scope.sortOptions.direction === 'desc'); + $scope.sortCache = { + data: $scope.filtered.slice(), + predicate: $scope.sortOptions.predicate, + direction: $scope.sortOptions.direction + } + } + $scope._time.sort = Date.now() - time3; + $scope._time.all = Date.now() - time; $scope.paginationOptions.totalItems = $scope.filtered.length; } @@ -316,7 +339,7 @@ if (serverPagination) { element.attr('ng-repeat', "item in filtered"); } else { - element.attr('ng-repeat', "item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage"); + element.attr('ng-repeat', "item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"); } $compile(element)(childScope); }); @@ -336,7 +359,7 @@ function textFilter(items, value, predicate) { return items.filter(function (item) { - return value && item[predicate] ? ~item[predicate].toLowerCase().indexOf(value.toLowerCase()) : true; + return value && item[predicate] ? ~(item[predicate] + '').toLowerCase().indexOf(value.toLowerCase()) : true; }); } From 69a94efb8c76bf82e7d831a784066dcc24fb5c35 Mon Sep 17 00:00:00 2001 From: "Zhuk, Alexander" Date: Wed, 27 Jan 2016 12:46:54 +0300 Subject: [PATCH 2/2] text & links update --- README.md | 2 ++ demo/100k/index.html | 38 ++++++++++++++++++++------------------ demo/bootstrap/index.html | 2 +- demo/material/index.html | 2 +- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 05d49aa..47efc75 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Demo Bootstrap: http://angular-data-grid.github.io/demo/bootstrap/ Demo Material: http://angular-data-grid.github.io/demo/material/ +Demo 100k: http://angular-data-grid.github.io/demo/100k/ + ### Features - Does not have any hard-coded template so you can choose any mark-up you need, from basic `` layout to any `
` structure. - Easily switch between the most popular Bootstrap and Google Material theming, or apply your own CSS theme just by changing several CSS classes. diff --git a/demo/100k/index.html b/demo/100k/index.html index a4456d8..d0b6cc6 100644 --- a/demo/100k/index.html +++ b/demo/100k/index.html @@ -2,7 +2,7 @@ - Angular Data Grid - Bootstrap Design + Angular Data Grid - 100k example @@ -12,14 +12,16 @@

Angular Data Grid 100k Example

- Features enabled: sorting, filtering (using both in-grid and external controls), sync with browser URLs, - pagination and items-per-page functionality. - Angular UI Datepicker used for date controls, although you can use any other framework, plugin or styling. + This demonstrates client-side sorting / pagination / filtering performance of the data grid with 100 000 rows loaded at once. + It's not likely that someone will need to operate so huge data at client side in a real life, but for performance testing purposes it definitely works) Project GitHub

@@ -104,8 +106,8 @@

Angular Data Grid 100k Example

-
- {{filtered.length}} users total +
+ {{filtered.length}} users total
Time stats
Copy time: {{_time.copy}}
Filter time: {{_time.filters}}
@@ -190,18 +192,18 @@

Angular Data Grid 100k Example


-
- -
-

See the Pen xZddZm by AngularDataGrid (@AngularDataGrid) on CodePen. -

- -
-
-
+ + + + + + + + + + + +
diff --git a/demo/bootstrap/index.html b/demo/bootstrap/index.html index 3fc83d6..0faa477 100644 --- a/demo/bootstrap/index.html +++ b/demo/bootstrap/index.html @@ -21,7 +21,7 @@ Bootstrap Design
  • - Material Design + Material Design
  • diff --git a/demo/material/index.html b/demo/material/index.html index fec4eed..cc68643 100644 --- a/demo/material/index.html +++ b/demo/material/index.html @@ -24,7 +24,7 @@ - Bootstrap Design + Bootstrap Design Material Design