UNPKG

angular4-material-table

Version:

Angular 4 table based on @angular/cdk table structure, to allow row insertion, edition, validation and deletion.

476 lines (463 loc) 20.6 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/common'), require('@angular/core'), require('lodash.clonedeep'), require('@angular/cdk/collections'), require('rxjs')) : typeof define === 'function' && define.amd ? define(['exports', '@angular/common', '@angular/core', 'lodash.clonedeep', '@angular/cdk/collections', 'rxjs'], factory) : (factory((global.ng = global.ng || {}, global.ng['angular4-material-table'] = {}),global.ng.common,global.ng.core,global.index,global.ng.cdk.collections,null)); }(this, (function (exports,common,core,cloneDeep,collections,rxjs) { 'use strict'; cloneDeep = cloneDeep && cloneDeep.hasOwnProperty('default') ? cloneDeep['default'] : cloneDeep; var AppModule = /** @class */ (function () { function AppModule() { } AppModule.decorators = [ { type: core.NgModule, args: [{ declarations: [], imports: [ common.CommonModule ], exports: [] },] }, ]; return AppModule; }()); var ValidatorService = /** @class */ (function () { function ValidatorService() { } ValidatorService.decorators = [ { type: core.Injectable }, ]; return ValidatorService; }()); var DefaultValidatorService = /** @class */ (function () { function DefaultValidatorService() { } DefaultValidatorService.prototype.getRowValidator = function () { return null; }; DefaultValidatorService.decorators = [ { type: core.Injectable }, ]; return DefaultValidatorService; }()); var TableElement = /** @class */ (function () { function TableElement() { } TableElement.prototype.delete = function () { this.source.delete(this.id); }; TableElement.prototype.confirmEditCreate = function () { if (this.id == -1) return this.source.confirmCreate(this); else return this.source.confirmEdit(this); }; TableElement.prototype.startEdit = function () { this.originalData = cloneDeep(this.currentData); this.editing = true; }; TableElement.prototype.cancelOrDelete = function () { if (this.id == -1 || !this.editing) this.delete(); else { this.currentData = this.originalData; this.editing = false; } }; return TableElement; }()); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var TableElementReactiveForms = /** @class */ (function (_super) { __extends(TableElementReactiveForms, _super); function TableElementReactiveForms(init) { var _this = _super.call(this) || this; _this.validator = init.validator; Object.assign(_this, init); return _this; } Object.defineProperty(TableElementReactiveForms.prototype, "currentData", { get: function () { return this.validator.getRawValue(); }, set: function (data) { this.validator.patchValue(data); }, enumerable: true, configurable: true }); Object.defineProperty(TableElementReactiveForms.prototype, "editing", { get: function () { return this.validator.enabled; }, set: function (value) { if (value) { this.validator.enable(); } else { this.validator.disable(); } }, enumerable: true, configurable: true }); TableElementReactiveForms.prototype.isValid = function () { return this.validator.valid; }; return TableElementReactiveForms; }(TableElement)); var __extends$1 = (undefined && undefined.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var TableElementTemplateDriven = /** @class */ (function (_super) { __extends$1(TableElementTemplateDriven, _super); function TableElementTemplateDriven(init) { var _this = _super.call(this) || this; Object.assign(_this, init); return _this; } Object.defineProperty(TableElementTemplateDriven.prototype, "validator", { get: function () { return null; }, set: function (value) { }, enumerable: true, configurable: true }); Object.defineProperty(TableElementTemplateDriven.prototype, "currentData", { get: function () { return this._currentData; }, set: function (data) { this._currentData = data; }, enumerable: true, configurable: true }); Object.defineProperty(TableElementTemplateDriven.prototype, "editing", { get: function () { return this._editing; }, set: function (value) { this._editing = value; }, enumerable: true, configurable: true }); TableElementTemplateDriven.prototype.isValid = function () { return true; }; return TableElementTemplateDriven; }(TableElement)); var TableElementFactory = /** @class */ (function () { function TableElementFactory() { } TableElementFactory.createTableElement = function (newElement) { if (this.isValidatorDefined(newElement)) { // Create reactive forms element here. return new TableElementReactiveForms(newElement); } else { // Default is the one without validator. return new TableElementTemplateDriven(newElement); } }; TableElementFactory.isValidatorDefined = function (newElement) { return newElement.validator != null && newElement.validator != undefined; }; return TableElementFactory; }()); var __extends$2 = (undefined && undefined.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var TableDataSource = /** @class */ (function (_super) { __extends$2(TableDataSource, _super); /** * Creates a new TableDataSource instance, that can be used as datasource of `@angular/cdk` data-table. * @param data Array containing the initial values for the TableDataSource. If not specified, then `dataType` must be specified. * @param dataType Type of data contained by the Table. If not specified, then `data` with at least one element must be specified. * @param validatorService Service that create instances of the FormGroup used to validate row fields. * @param config Additional configuration for table. */ function TableDataSource(data, dataType, validatorService, config) { if (config === void 0) { config = { prependNewElements: false, suppressErrors: false }; } var _this = _super.call(this) || this; _this.validatorService = validatorService; _this.config = config; if (!validatorService) _this.validatorService = new DefaultValidatorService(); if (dataType) { _this.dataConstructor = dataType; } else { if (data && data.length > 0) _this.dataKeys = Object.keys(data[0]); else throw new Error('You must define either a non empty array, or an associated class to build the table.'); } _this.checkValidatorFields(_this.validatorService); _this.rowsSubject = new rxjs.BehaviorSubject(_this.getRowsFromData(data)); _this.datasourceSubject = new rxjs.Subject(); return _this; } TableDataSource.prototype.checkValidatorFields = function (validatorService) { var _this = this; var formGroup = validatorService.getRowValidator(); if (formGroup != null) { var rowKeys_1 = Object.keys(this.createNewObject()); Object.keys(formGroup.controls).forEach(function (key) { if (rowKeys_1.some(function (x) { return x === key; })) { _this.logError('Validator form control keys must match row object keys.'); } }); } }; TableDataSource.prototype.logError = function (message) { if (!this.config.suppressErrors) console.error(message); }; /** * Start the creation of a new element, pushing an empty-data row in the table. */ TableDataSource.prototype.createNew = function () { var source = this.rowsSubject.getValue(); if (!this.existsNewElement(source)) { var newElement = TableElementFactory.createTableElement({ id: -1, editing: true, currentData: this.createNewObject(), source: this, validator: this.validatorService.getRowValidator(), }); if (this.config.prependNewElements) { this.rowsSubject.next([newElement].concat(source)); } else { source.push(newElement); this.rowsSubject.next(source); } } }; /** * Confirm creation of the row. Save changes and disable editing. * If validation active and row data is invalid, it doesn't confirm creation neither disable editing. * @param row Row to be confirmed. */ TableDataSource.prototype.confirmCreate = function (row) { if (!row.isValid()) { return false; } var source = this.rowsSubject.getValue(); row.id = source.length - 1; this.rowsSubject.next(source); row.editing = false; this.updateDatasourceFromRows(source); return true; }; /** * Confirm edition of the row. Save changes and disable editing. * If validation active and row data is invalid, it doesn't confirm editing neither disable editing. * @param row Row to be edited. */ TableDataSource.prototype.confirmEdit = function (row) { if (!row.isValid()) { return false; } var source = this.rowsSubject.getValue(); var index = this.getIndexFromRowId(row.id, source); source[index] = row; this.rowsSubject.next(source); row.originalData = undefined; row.editing = false; this.updateDatasourceFromRows(source); return true; }; /** * Delete the row with the index specified. */ TableDataSource.prototype.delete = function (id) { var source = this.rowsSubject.getValue(); var index = this.getIndexFromRowId(id, source); source.splice(index, 1); this.updateRowIds(index, source); this.rowsSubject.next(source); if (id != -1) this.updateDatasourceFromRows(source); }; /** * Get row from the table. * @param id Id of the row to retrieve, -1 returns the current new line. */ TableDataSource.prototype.getRow = function (id) { var source = this.rowsSubject.getValue(); var index = this.getIndexFromRowId(id, source); return (index >= 0 && index < source.length) ? source[index] : null; }; /** * Update the datasource with a new array of data. If the array reference * is the same as the previous one, it doesn't trigger an update. * @param data Data to update the table datasource. * @param options Specify options to update the datasource. * If emitEvent is true and the datasource is updated, it emits an event * from 'datasourceSubject' with the updated data. If false, it doesn't * emit an event. True by default. */ TableDataSource.prototype.updateDatasource = function (data, options) { if (options === void 0) { options = { emitEvent: true }; } if (this.currentData !== data) { this.currentData = data; this.rowsSubject.next(this.getRowsFromData(data)); if (options.emitEvent) this.datasourceSubject.next(data); } }; /** * Checks the existance of the a new row (not yet saved). * @param source */ TableDataSource.prototype.existsNewElement = function (source) { return !(source.length == 0 || source[this.getNewRowIndex(source)].id > -1); }; /** * Returns the possible index of the new row depending on the insertion type. * It doesn't imply that the new row is created, that must be checked. * @param source */ TableDataSource.prototype.getNewRowIndex = function (source) { if (this.config.prependNewElements) return 0; else return source.length - 1; }; /** * Returns the row id from the index specified. It does * not consider if the new row is present or not, assumes * that new row is not present. * @param index Index of the array. * @param count Quantity of elements in the array. */ TableDataSource.prototype.getRowIdFromIndex = function (index, count) { if (this.config.prependNewElements) return count - 1 - index; else return index; }; /** * Returns the index from the row id specified. * It takes into account if the new row exists or not. * @param id * @param source */ TableDataSource.prototype.getIndexFromRowId = function (id, source) { if (id == -1) { return this.existsNewElement(source) ? this.getNewRowIndex(source) : -1; } else { if (this.config.prependNewElements) return source.length - 1 - id; else return id; } }; /** * Update rows ids in the array specified, starting in the specified index * until the start/end of the array, depending on config.prependNewElements * configuration. * @param initialIndex Initial index of source to be updated. * @param source Array that contains the rows to be updated. */ TableDataSource.prototype.updateRowIds = function (initialIndex, source) { var delta = this.config.prependNewElements ? -1 : 1; for (var index = initialIndex; index < source.length && index >= 0; index += delta) { if (source[index].id != -1) source[index].id = this.getRowIdFromIndex(index, source.length); } }; /** * Get the data from the rows. * @param rows Rows to extract the data. */ TableDataSource.prototype.getDataFromRows = function (rows) { return rows .filter(function (row) { return row.id != -1; }) .map(function (row) { return row.originalData ? row.originalData : row.currentData; }); }; /** * Update the datasource with the data contained in the specified rows. * @param rows Rows that contains the datasource's new data. */ TableDataSource.prototype.updateDatasourceFromRows = function (rows) { this.currentData = this.getDataFromRows(rows); this.datasourceSubject.next(this.currentData); }; /** * From an array of data, it returns rows containing the original data. * @param arrayData Data from which create the rows. */ TableDataSource.prototype.getRowsFromData = function (arrayData) { var _this = this; return arrayData.map(function (data, index) { return TableElementFactory.createTableElement({ id: _this.getRowIdFromIndex(index, arrayData.length), editing: false, currentData: data, source: _this, validator: _this.validatorService.getRowValidator(), }); }); }; /** * Create a new object with identical structure than the table source data. * It uses the object's type contructor if available, otherwise it creates * an object with the same keys of the first element contained in the original * datasource (used in the constructor). */ TableDataSource.prototype.createNewObject = function () { if (this.dataConstructor) { return new this.dataConstructor(); } else { return this.dataKeys.reduce(function (obj, key) { obj[key] = undefined; return obj; }, {}); } }; /** Connect function called by the table to retrieve one stream containing * the data to render. */ TableDataSource.prototype.connect = function () { return this.rowsSubject.asObservable(); }; TableDataSource.prototype.disconnect = function () { }; return TableDataSource; }(collections.DataSource)); exports.AppModule = AppModule; exports.ValidatorService = ValidatorService; exports.DefaultValidatorService = DefaultValidatorService; exports.TableDataSource = TableDataSource; exports.TableElement = TableElement; exports.TableElementTemplateDriven = TableElementTemplateDriven; exports.TableElementReactiveForms = TableElementReactiveForms; Object.defineProperty(exports, '__esModule', { value: true }); })));