ng-table
Version:
Table + AngularJS ================= [](https://travis-ci.org/esvit/ng-table) [](https://coveralls.io/r/esvit/ng-table) [![seman
256 lines • 11.1 kB
JavaScript
/**
* ngTable: Table + Angular JS
*
* @author Vitalii Savchuk <esvit666@gmail.com>
* @url https://github.com/esvit/ng-table/
* @license New BSD License <http://creativecommons.org/licenses/BSD/>
*/
import * as ng1 from 'angular';
import { NgTableParams } from '../core';
/**
* The controller for the {@link ngTable ngTable} and {@link ngTableDynamic ngTableDynamic} directives
*/
export var NgTableController = (function () {
function NgTableController($scope, $timeout, $parse, $compile, $attrs, $element, $document, ngTableColumn, ngTableEventsChannel) {
this.$scope = $scope;
this.$parse = $parse;
this.$compile = $compile;
this.$attrs = $attrs;
this.$element = $element;
this.$document = $document;
this.ngTableColumn = ngTableColumn;
this.ngTableEventsChannel = ngTableEventsChannel;
var isFirstTimeLoad = true;
$scope.$filterRow = { disabled: false };
$scope.$loading = false;
// until such times as the directive uses an isolated scope, we need to ensure that the check for
// the params field only consults the "own properties" of the $scope. This is to avoid seeing the params
// field on a $scope higher up in the prototype chain
if (!$scope.hasOwnProperty("params")) {
$scope.params = new NgTableParams(true);
}
this.delayFilter = (function () {
var timer;
return function (callback, ms) {
$timeout.cancel(timer);
timer = $timeout(callback, ms);
};
})();
// watch for when a new NgTableParams is bound to the scope
// CRITICAL: the watch must be for reference and NOT value equality; this is because NgTableParams maintains
// the current data page as a field. Checking this for value equality would be terrible for performance
// and potentially cause an error if the items in that array has circular references
this.$scope.$watch('params', function (newParams, oldParams) {
if (newParams === oldParams || !newParams) {
return;
}
newParams.reload();
}, false);
this.subscribeToTableEvents();
}
Object.defineProperty(NgTableController.prototype, "hasVisibleFilterColumn", {
get: function () {
var _this = this;
if (!this.$scope.$columns)
return false;
return this.some(this.$scope.$columns, function ($column) {
return $column.show(_this.$scope) && !!$column.filter(_this.$scope);
});
},
enumerable: true,
configurable: true
});
NgTableController.prototype.onDataReloadStatusChange = function (newStatus /*, oldStatus*/) {
if (!newStatus || this.$scope.params.hasErrorState()) {
return;
}
var currentParams = this.$scope.params;
var filterOptions = currentParams.settings().filterOptions;
if (currentParams.hasFilterChanges()) {
var applyFilter = function () {
currentParams.page(1);
currentParams.reload();
};
if (filterOptions.filterDelay) {
this.delayFilter(applyFilter, filterOptions.filterDelay);
}
else {
applyFilter();
}
}
else {
currentParams.reload();
}
};
NgTableController.prototype.compileDirectiveTemplates = function () {
if (!this.$element.hasClass('ng-table')) {
this.$scope.templates = {
header: (this.$attrs.templateHeader ? this.$attrs.templateHeader : 'ng-table/header.html'),
pagination: (this.$attrs.templatePagination ? this.$attrs.templatePagination : 'ng-table/pager.html')
};
this.$element.addClass('ng-table');
var headerTemplate = null;
// $element.find('> thead').length === 0 doesn't work on jqlite
var theadFound_1 = false;
ng1.forEach(this.$element.children(), function (e) {
if (e.tagName === 'THEAD') {
theadFound_1 = true;
}
});
if (!theadFound_1) {
headerTemplate = ng1.element('<thead ng-include="templates.header"></thead>', this.$document);
this.$element.prepend(headerTemplate);
}
var paginationTemplate = ng1.element('<div ng-table-pagination="params" template-url="templates.pagination"></div>', this.$document);
this.$element.after(paginationTemplate);
if (headerTemplate) {
this.$compile(headerTemplate)(this.$scope);
}
this.$compile(paginationTemplate)(this.$scope);
}
};
NgTableController.prototype.loadFilterData = function ($columns) {
var _this = this;
ng1.forEach($columns, function ($column) {
var result = $column.filterData(_this.$scope);
if (!result) {
delete $column.filterData;
return undefined;
}
if (isPromiseLike(result)) {
delete $column.filterData;
return result.then(function (data) {
// our deferred can eventually return arrays, functions and objects
if (!ng1.isArray(data) && !ng1.isFunction(data) && !ng1.isObject(data)) {
// if none of the above was found - we just want an empty array
data = [];
}
$column.data = data;
});
}
else {
return $column.data = result;
}
});
function isPromiseLike(val) {
return val && typeof val === 'object' && typeof val.then === 'function';
}
};
NgTableController.prototype.buildColumns = function (columns) {
var _this = this;
// todo: use strictNullChecks and remove guard clause
var result = [];
(columns || []).forEach(function (col) {
result.push(_this.ngTableColumn.buildColumn(col, _this.$scope, result));
});
return result;
};
NgTableController.prototype.parseNgTableDynamicExpr = function (attr) {
if (!attr || attr.indexOf(" with ") > -1) {
var parts = attr.split(/\s+with\s+/);
return {
tableParams: parts[0],
columns: parts[1]
};
}
else {
throw new Error('Parse error (expected example: ng-table-dynamic=\'tableParams with cols\')');
}
};
NgTableController.prototype.setupBindingsToInternalScope = function (tableParamsExpr) {
// note: this we're setting up watches to simulate angular's isolated scope bindings
var _this = this;
// note: is REALLY important to watch for a change to the ngTableParams *reference* rather than
// $watch for value equivalence. This is because ngTableParams references the current page of data as
// a field and it's important not to watch this
this.$scope.$watch(tableParamsExpr, function (params) {
if (params === undefined) {
return;
}
_this.$scope.params = params;
}, false);
this.setupFilterRowBindingsToInternalScope();
this.setupGroupRowBindingsToInternalScope();
};
NgTableController.prototype.setupFilterRowBindingsToInternalScope = function () {
var _this = this;
if (this.$attrs.showFilter) {
this.$scope.$parent.$watch(this.$attrs.showFilter, function (value) {
_this.$scope.show_filter = value;
});
}
else {
this.$scope.$watch(function () { return _this.hasVisibleFilterColumn; }, function (value) {
_this.$scope.show_filter = value;
});
}
if (this.$attrs.disableFilter) {
this.$scope.$parent.$watch(this.$attrs.disableFilter, function (value) {
_this.$scope.$filterRow.disabled = value;
});
}
};
NgTableController.prototype.setupGroupRowBindingsToInternalScope = function () {
var _this = this;
this.$scope.$groupRow = { show: false };
if (this.$attrs.showGroup) {
var showGroupGetter_1 = this.$parse(this.$attrs.showGroup);
this.$scope.$parent.$watch(showGroupGetter_1, function (value) {
_this.$scope.$groupRow.show = value;
});
if (showGroupGetter_1.assign) {
// setup two-way databinding thus allowing ngTableGrowRow to assign to the showGroup expression
this.$scope.$watch('$groupRow.show', function (value) {
showGroupGetter_1.assign(_this.$scope.$parent, value);
});
}
}
else {
this.$scope.$watch('params.hasGroup()', function (newValue) {
_this.$scope.$groupRow.show = newValue;
});
}
};
NgTableController.prototype.getVisibleColumns = function () {
var _this = this;
return (this.$scope.$columns || []).filter(function (c) {
return c.show(_this.$scope);
});
};
NgTableController.prototype.subscribeToTableEvents = function () {
var _this = this;
this.$scope.$watch('params.isDataReloadRequired()', function (newStatus /*, oldStatus*/) {
_this.onDataReloadStatusChange(newStatus);
});
this.ngTableEventsChannel.onAfterReloadData(function (params, newDatapage) {
var visibleColumns = _this.getVisibleColumns();
if (params.hasGroup()) {
_this.$scope.$groups = (newDatapage || []);
_this.$scope.$groups.visibleColumnCount = visibleColumns.length;
}
else {
_this.$scope.$data = (newDatapage || []);
_this.$scope.$data.visibleColumnCount = visibleColumns.length;
}
}, this.$scope, function (publisher) { return _this.$scope.params === publisher; });
this.ngTableEventsChannel.onPagesChanged(function (params, newPages) {
_this.$scope.pages = newPages;
}, this.$scope, function (publisher) { return _this.$scope.params === publisher; });
};
NgTableController.prototype.some = function (array, predicate) {
var found = false;
for (var i = 0; i < array.length; i++) {
var obj = array[i];
if (predicate(obj)) {
found = true;
break;
}
}
return found;
};
NgTableController.$inject = [
'$scope', '$timeout', '$parse', '$compile', '$attrs', '$element', '$document', 'ngTableColumn', 'ngTableEventsChannel'
];
return NgTableController;
}());
//# sourceMappingURL=ngTableController.js.map