-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
jQuery DataTables and Editor - the evil #124
Comments
angular-datatablesangular-datatables官方文档: http://l-lin.github.io/angular-datatables/archives/ 主要有两种模式, Angular way就是在html中用ng-repeat构建表格, 需要给table加上 Ajax是在html中定义一个没有thead和tbody的table ,加上 如果要使用bootstrap的样式, 见http://l-lin.github.io/angular-datatables/archives/#!/bootstrapIntegration 这部分. 如果要使用分页功能, 一开始会被 如果要使用server side分页, 不能用angular way, 只能用ajax. DataTables要求服务端响应如下数据格式 {
"draw": 1,
"recordsTotal": 57,
"recordsFiltered": 5,
"data": [...]
} 可以在callback中做一个数据格式变换, 参见下面我封装的utils.js 如果要使用scroller插件, 也不能用angular way, 只能用ajax, 不然在窗口resize的时候固定表头不会随窗口动态调整宽度. |
在angularjs run中设置DataTables默认值app.run(runBlock);
/** @ngInject */
function runBlock($log, $rootScope, $state, DTDefaultOptions, config) {
$rootScope.$state = $state;
$rootScope.config = config;
DTDefaultOptions.setLanguage({
"sEmptyTable": "テーブルにデータがありません",
"sProcessing": '<img src="assets/images/ajax-loader.gif">', // #008A8A
});
DTDefaultOptions.setOption('bSort', false);
DTDefaultOptions.setOption('bFilter', false);
DTDefaultOptions.setOption('bPaginate', false);
DTDefaultOptions.setOption('bInfo', false);
}
/** @ngInject */
app.factory('_', ['$window', function ($window) {
// see https://stackoverflow.com/questions/14968297/use-underscore-inside-angular-controllers
return $window._;
}]); ajax有两种使用方法: var dtOptions = DTOptionsBuilder.newOptions()
.withOption('ajax', {
url: config.api + '/categories/v1',
method: 'GET'
}).withDataProp('items'); 还有一种, 可以在ajax中使用callback(服务端分页需要) dtOptions.withOption('ajax', function (data, callback, settings) {
}); 我觉得fromFnPromise更好, 因为后者可以使用$http服务, 加入http interceptors后能对请求进行统一处理. fromFnPromise文档中写的return deferred.promise那种方式已经不能用了, 看了源代码才知道要像下面这样写: var dtOptions = DTOptionsBuilder.fromFnPromise(function () {
return $http.get(config.api + '/categories/v1');
}).withOption('sAjaxDataProp', 'data.items'); createdRow为了能在renderWith的返回值中使用angular directive, 需要加上如下createdRow选项, 它会使用$compile服务对renderWith的值进行scope绑定. dtOptions.withOption('createdRow', function (row, data, dataIndex) {
// Create a new scope for each row, otherwise, data will
// not be unique for each row because of data bindings
var $scope = scope;
var $newScope = $scope.$new(true);
$newScope.row = data;
// Pass any methods you are using in current scope
$newScope.delete = $scope.delete;
return $timeout(function () {
// Recompiling so we can bind Angular directive to the DT
return $scope.$apply($compile(angular.element(row).contents())($newScope));
});
}); 这样能在renderWith的模板中使用row来访问当前行的数据(不需要使用renderWith传入的参数) 在angular-datatables的文档中使用了更简洁的方式 function BindAngularDirectiveCtrl($scope, $compile, DTOptionsBuilder, DTColumnBuilder) {
var vm = this;
vm.message = '';
vm.edit = edit;
vm.delete = deleteRow;
vm.dtInstance = {};
vm.persons = {};
vm.dtOptions = DTOptionsBuilder.fromSource('data1.json')
.withPaginationType('full_numbers')
.withOption('createdRow', createdRow);
vm.dtColumns = [
DTColumnBuilder.newColumn('id').withTitle('ID'),
DTColumnBuilder.newColumn('firstName').withTitle('First name'),
DTColumnBuilder.newColumn('lastName').withTitle('Last name'),
DTColumnBuilder.newColumn(null).withTitle('Actions').notSortable()
.renderWith(actionsHtml)
];
function edit(person) {
vm.message = 'You are trying to edit the row: ' + JSON.stringify(person);
// Edit some data and call server to make changes...
// Then reload the data so that DT is refreshed
vm.dtInstance.reloadData();
}
function deleteRow(person) {
vm.message = 'You are trying to remove the row: ' + JSON.stringify(person);
// Delete some data and call server to make changes...
// Then reload the data so that DT is refreshed
vm.dtInstance.reloadData();
}
function createdRow(row, data, dataIndex) {
// Recompiling so we can bind Angular directive to the DT
$compile(angular.element(row).contents())($scope);
}
function actionsHtml(data, type, full, meta) {
vm.persons[data.id] = data;
return '<button class="btn btn-warning" ng-click="showCase.edit(showCase.persons[' + data.id + '])">' +
' <i class="fa fa-edit"></i>' +
'</button> ' +
'<button class="btn btn-danger" ng-click="showCase.delete(showCase.persons[' + data.id + '])" )"="">' +
' <i class="fa fa-trash-o"></i>' +
'</button>';
}
} dt-instance如果要重绘表格可以使用vm.dtInstance.rerender(), 给vm.dtInstance设置值有两种方法: 直接设定一个变量 vm.dtInstance = {}; <table datatable="" dt-options="vm.dtOptions" dt-columns="vm.dtColumns" dt-instance="vm.dtInstance"
class="table table-bordered table-hover dataTables-example">
</table> 回调函数(可以设置多个instance) vm.dtInstances = [];
vm.dtInstCallback = function (dtInstance) {
vm.dtInstances.push(dtInstance);
} <table datatable="" dt-options="vm.dtOptions" dt-columns="vm.dtColumns" dt-instance="vm.dtInstCallback"
class="table table-bordered table-hover dataTables-example">
</table> Fixed table header(scroller)需要加入依赖
// Code for fixed table header
vm.dtInstances = [];
vm.dtOptions = DTOptionsBuilder.newOptions()
.withScroller()
.withOption('scrollY', 152); // 5 rows
vm.dtInstCallback = function (dtInstance) {
vm.dtInstances.push(dtInstance);
// resize fixed table header on window resize
var onResize = _.throttle(_.bind(dtInstance.rerender, dtInstance), 1000);
function cleanUp() {
angular.element($window).off('resize', onResize);
console.log('cleanUp');
}
angular.element($window).on('resize', onResize);
$scope.$on('$destroy', cleanUp);
}; 如果给table加上min-width/width会出现水平滚动条, 这个时候fixed header不会随着滚动条一起滚动, 见: .withOption('bAutoWidth', false) FixedColumn |
server side pagination我这写了一个工具类. (function () {
'use strict';
angular.module('myapp')
.factory('utils', utils);
/** @ngInject */
function utils($http, $compile, $timeout, DTOptionsBuilder, config) {
return {
calcRowNumber: function (vm, meta) {
return (vm.pageParams.page - 1) * vm.pageParams.limit + meta.row + 1;
},
useNgDirective: function (dtOptions, scope) {
// see https://stackoverflow.com/questions/36911340/how-to-access-current-row-data-in-angular-datatables-using-templates
dtOptions.withOption('createdRow', function (row, data, dataIndex) {
// Create a new scope for each row, otherwise, data will
// not be unique for each row because of data bindings
var $scope = scope;
var $newScope = $scope.$new(true);
$newScope.row = data;
// Pass any methods you are using in current scope
$newScope.delete = $scope.delete;
return $timeout(function () {
// Recompiling so we can bind Angular directive to the DT
return $scope.$apply($compile(angular.element(row).contents())($newScope));
});
});
},
enableServerSidePagination: function (vm, options) {
options = options || {};
options.limit = options.limit || 10;
var dtOptions = DTOptionsBuilder.newOptions();
dtOptions.withOption('ajax', function (data, callback, settings) {
// make an ajax request using data.start and data.length
var limit = data.length;
var page = data.start / limit + 1;
$http.get(config.api + options.url,
{params: {page: page, limit: limit}})
.success(function (res) {
// map your server's response to the DataTables format and pass it to
// DataTables' callback
var pageParams = {
total: res.total,
page: page,
limit: res.limit
};
vm.pageParams = pageParams;
callback({
recordsTotal: res.total,
recordsFiltered: res.total,
data: res.items
});
});
});
if(options.ng && options.scope) {
this.useNgDirective(dtOptions, options.scope);
}
/*
see https://datatables.net/reference/option/dom
l - length changing input control
f - filtering input
t - The table!
i - Table information summary
p - pagination control
r - processing display element
*/
dtOptions
.withOption('bPaginate', true)
.withOption('bInfo', true)
.withDOM('rtip')
.withOption('processing', true)
.withOption('serverSide', true)
.withPaginationType('full_numbers')
.withDataProp('data')
.withDisplayLength(options.limit)
.withBootstrap();
vm.dtOptions = dtOptions;
}
};
}
})(); 用法如下: vm.dtInstance = {};
// 反注释这行使用服务端分页
//utils.enableServerSidePagination(vm, {url: '/categories/v1', ng: true, scope: $scope});
var dtOptions = DTOptionsBuilder.fromFnPromise(function () {
return $http.get(config.api + '/categories/v1');
}).withOption('sAjaxDataProp', 'data.items');
utils.useNgDirective(dtOptions, $scope);
dtOptions.withScroller().withOption('scrollY', 200);
vm.dtOptions = dtOptions;
vm.dtColumns = [
// DTColumnBuilder.newColumn(null).withTitle('#').renderWith(function (data, type, full, meta) {
// return utils.calcRowNumber(vm, meta);
// }),
DTColumnBuilder.newColumn('name').withTitle('Name').renderWith(function (data) {
return '{{row.name|limitTo: 5}}';
}),
DTColumnBuilder.newColumn('createdDate')
.withClass('text-center')
.withTitle('Created Date')
.renderWith(function (data, type, full, meta) {
return $filter('date')(data, 'yyyy/MM/dd');
}),
DTColumnBuilder.newColumn('customProperty').withTitle('Custom Property').notVisible(),
DTColumnBuilder.newColumn('id').withTitle('Link').renderWith(function () {
return '<a ui-sref="index.some({id:row.id})">some link</a>';
})
]; |
datatables callback在datatables渲染完table后会回调 fnDrawCallback, 可以在withOption中注册这个回调函数. |
https://datatables.net/ and https://editor.datatables.net/
Compare jsgrid and datatables Getting Started Page
DataTables Getting Started
jsgrid Getting Started
I think you should already make up your mind now. the former very complex and hard to know what it says
The latter, simple and to the point, the clear interface includes all the functions that a table editor requires.
吐槽 Complaint
DataTables所有的列都要指定fields和columns (N多重复代码)
data, visible, className要定义在column里边, name, type要定义在fields里边, WTF?
jsgrid只要定义fields: name, visible和type等一个field轻松搞定, no brain-fuck.
DataTables的下拉框真的难用, 文档在tech notes里边(难找吧!)
https://datatables.net/manual/tech-notes/11
下拉字段是下面这样的形式
fields.push({name: 'FieldName', type: 'select', options: [{label:'', value:''}, ...] });
其中options必须是这种指定格式. 需要提前转换, jsgrid没有这个限制(无需转换)..
DataTables的editor还是收费的. 依赖一大堆组合, buttons是一个js, select又是一个js, 到底要下载哪些js分分钟把你搞晕
DataTables出了错竟然是弹出alert(这也太不友好了, 在console.log中打印出来不更好)
关键是warning类型的没有必要弹alert.
如何禁掉这个alert在此:
https://datatables.net/forums/discussion/28726/how-to-disable-the-warning-message
小技巧
访问nested array, 像这样:
friends.0.name
,friends.1.name
references
https://datatables.net/forums/discussion/29339/change-ajax-url
https://editor.datatables.net/reference/option/ajax.data
https://editor.datatables.net/reference/field/select
The text was updated successfully, but these errors were encountered: