@universis/ngx-tables 0.8.4 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/bundles/universis-ngx-tables.umd.js +143 -104
  2. package/bundles/universis-ngx-tables.umd.js.map +1 -1
  3. package/bundles/universis-ngx-tables.umd.min.js +1 -1
  4. package/bundles/universis-ngx-tables.umd.min.js.map +1 -1
  5. package/esm2015/lib/components/advanced-table/advanced-table.component.js +119 -95
  6. package/esm2015/lib/components/advanced-table/advanced-table.formatters.js +5 -3
  7. package/esm2015/lib/components/advanced-table/advanced-table.interfaces.js +1 -1
  8. package/esm2015/lib/components/column-selector/column-selector.component.js +26 -14
  9. package/esm2015/lib/components/column-selector/column-selector.service.js +1 -1
  10. package/esm2015/lib/directives/advance-table-state.directive.js +2 -1
  11. package/esm5/lib/components/advanced-table/advanced-table.component.js +119 -95
  12. package/esm5/lib/components/advanced-table/advanced-table.formatters.js +5 -3
  13. package/esm5/lib/components/advanced-table/advanced-table.interfaces.js +1 -1
  14. package/esm5/lib/components/column-selector/column-selector.component.js +24 -11
  15. package/esm5/lib/components/column-selector/column-selector.service.js +1 -1
  16. package/esm5/lib/directives/advance-table-state.directive.js +1 -1
  17. package/fesm2015/universis-ngx-tables.js +147 -107
  18. package/fesm2015/universis-ngx-tables.js.map +1 -1
  19. package/fesm5/universis-ngx-tables.js +144 -105
  20. package/fesm5/universis-ngx-tables.js.map +1 -1
  21. package/lib/components/advanced-table/advanced-table.interfaces.d.ts +1 -0
  22. package/lib/components/column-selector/column-selector.component.d.ts +4 -5
  23. package/package.json +1 -1
  24. package/universis-ngx-tables.metadata.json +1 -1
@@ -192,11 +192,13 @@ class ActionLinkFormatter extends AdvancedColumnFormatter {
192
192
  }
193
193
  if (x.formatOptions && x.formatOptions.commands) {
194
194
  const urlTree = this.createUrlTree(row, x.formatOptions);
195
- return `<a data-name='${x.name}' class="dropdown-item" href="#${urlTree.toString()}">
195
+ return `<a data-name='${x.name}' class="dropdown-item${typeof x.className === 'string' && x.className.length
196
+ ? ` ${x.className.trim()}` : ''}" href="#${urlTree.toString()}">
196
197
  ${this.injector.get(TranslateService).instant(x.title)}
197
198
  </a>`;
198
199
  }
199
- return `<a data-name='${x.name}' class="dropdown-item" href="${AdvancedColumnFormatter.template(x.href)(row)}">
200
+ return `<a data-name='${x.name}' class="dropdown-item${typeof x.className === 'string' && x.className.length
201
+ ? ` ${x.className.trim()}` : ''}" href="${AdvancedColumnFormatter.template(x.href)(row)}">
200
202
  ${this.injector.get(TranslateService).instant(x.title)}
201
203
  </a>`;
202
204
  })
@@ -479,19 +481,32 @@ AdvancedFilterValueProvider.decorators = [
479
481
  AdvancedFilterValueProvider.ctorParameters = () => [];
480
482
  AdvancedFilterValueProvider.ngInjectableDef = defineInjectable({ factory: function AdvancedFilterValueProvider_Factory() { return new AdvancedFilterValueProvider(); }, token: AdvancedFilterValueProvider, providedIn: "root" });
481
483
 
484
+ // tslint:disable-next-line:max-line-length
482
485
  class ColumnSelectorComponent extends RouterModalOkCancel {
483
- constructor(router, activatedRoute, _modalRef, ref, _translateService) {
486
+ constructor(router, activatedRoute, _modalRef, _changeDetector) {
484
487
  super(router, activatedRoute);
485
488
  this._modalRef = _modalRef;
486
- this.ref = ref;
487
- this._translateService = _translateService;
489
+ this._changeDetector = _changeDetector;
488
490
  this.dismiss = new EventEmitter();
489
491
  this.availableColumnsControl = new FormControl();
490
492
  this.selectedColumnsControl = new FormControl();
493
+ this.changing = false;
491
494
  }
492
495
  ok() {
493
- this._modalRef.hide();
494
- this.applyChanges();
496
+ this._changeDetector.detectChanges();
497
+ setTimeout(() => {
498
+ this.changing = true;
499
+ this._modalRef.hide();
500
+ }, 0);
501
+ try {
502
+ this.applyChanges();
503
+ }
504
+ catch (err) {
505
+ throw err;
506
+ }
507
+ finally {
508
+ this.changing = false;
509
+ }
495
510
  this.dismiss.emit('ok');
496
511
  return Promise.resolve('ok');
497
512
  }
@@ -547,7 +562,7 @@ class ColumnSelectorComponent extends RouterModalOkCancel {
547
562
  const selected = this.selectedColumnsControl.value;
548
563
  if (selected.length > 0) {
549
564
  for (const value of selected) {
550
- let findIndex = this.selectedColumns.findIndex((item) => {
565
+ const findIndex = this.selectedColumns.findIndex((item) => {
551
566
  return item.key === value;
552
567
  });
553
568
  if (findIndex >= 0) {
@@ -562,7 +577,7 @@ class ColumnSelectorComponent extends RouterModalOkCancel {
562
577
  const selected = this.availableColumnsControl.value;
563
578
  if (selected.length > 0) {
564
579
  for (const value of selected) {
565
- let findColumn = this.columns.find((item) => {
580
+ const findColumn = this.columns.find((item) => {
566
581
  return item.key === value;
567
582
  });
568
583
  if (findColumn) {
@@ -612,7 +627,7 @@ class ColumnSelectorComponent extends RouterModalOkCancel {
612
627
  const selected = this.selectedColumnsControl.value;
613
628
  if (selected.length > 0) {
614
629
  for (const value of selected) {
615
- let findIndex = this.selectedColumns.findIndex((item) => {
630
+ const findIndex = this.selectedColumns.findIndex((item) => {
616
631
  return item.key === value;
617
632
  });
618
633
  const length = this.columns.length;
@@ -628,8 +643,9 @@ class ColumnSelectorComponent extends RouterModalOkCancel {
628
643
  }
629
644
  ColumnSelectorComponent.decorators = [
630
645
  { type: Component, args: [{
646
+ // tslint:disable-next-line:component-selector
631
647
  selector: 'app-column-selector',
632
- template: "<div>\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">{{'Tables.SelectColumns' | translate}}</h5>\n <button (click)=\"cancel()\"\n type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Cancel\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n <div class=\"modal-body pt-0\">\n <div class=\"row\">\n <div class=\"col-12\">\n <p [translate]=\"'Tables.SelectColumnHelp'\"></p>\n <p [translate]=\"'Tables.MoveColumnHelp'\"></p>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-4\">\n <select [formControl]=\"availableColumnsControl\" size=\"10\" class=\"form-select form-control\" multiple aria-label=\"multiple select example\">\n <ng-container *ngIf=\"columns\">\n <ng-container *ngFor=\"let column of columns | orderBy: ['title']\">\n <option class=\"text-wrap\" [value]=\"column.key\">{{column.title}}</option>\n </ng-container>\n </ng-container>\n </select>\n </div>\n <div class=\"col-4 d-flex justify-content-center align-items-center\">\n <div class=\"col-9\">\n <div>\n <button [disabled]=\"!(availableColumnsControl.value && availableColumnsControl.value.length)\" (click)=\"addColumns()\" type=\"button\" class=\"btn btn-primary btn-block\">\n <i class=\"fas fa-plus mr-2\"></i><span [translate]=\"'Tables.AddColumn'\"></span>\n </button>\n </div>\n <div class=\"mt-3\">\n <button [disabled]=\"!(selectedColumnsControl.value && selectedColumnsControl.value.length)\" (click)=\"removeColumns()\" type=\"button\" class=\"btn btn-secondary btn-block\">\n <i class=\"fas fa-minus mr-2\"></i><span [translate]=\"'Tables.RemoveColumn'\"></span>\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-4\">\n <select [formControl]=\"selectedColumnsControl\" size=\"10\" class=\"form-select form-control\" multiple aria-label=\"multiple select example\">\n <ng-container *ngIf=\"selectedColumns\">\n <ng-container *ngFor=\"let column of selectedColumns\">\n <option class=\"text-wrap\" [value]=\"column.key\">{{column.title}}</option>\n </ng-container>\n </ng-container>\n </select>\n <div class=\"d-flex justify-content-center align-items-center\">\n <div class=\"btn-group mt-4\">\n <button #moveUpButton (click)=\"moveUp()\" type=\"button\" class=\"btn btn-primary\">\n <i class=\"fas fa-chevron-up mr-2\"></i><span [translate]=\"'Tables.MoveUp'\"></span>\n </button>\n <button #moveDownButton (click)=\"moveDown()\" type=\"button\" class=\"btn btn-primary ml-2\">\n <i class=\"fas fa-chevron-down mr-2\"></i><span [translate]=\"'Tables.MoveDown'\"></span>\n </button>\n </div>\n </div>\n </div>\n </div>\n \n </div>\n <div class=\"modal-footer justify-content-end\">\n <button [disabled]=\"okButtonDisabled\" (click)=\"ok()\"\n type=\"button\" class=\"btn btn-primary\">\n {{'OK' | translate}}\n </button>\n <button [disabled]=\"cancelButtonDisabled\"\n (click)=\"cancel()\" type=\"button\" [ngClass]=\"cancelButtonClass\" data-dismiss=\"modal\">\n {{'Cancel' | translate}}\n </button>\n </div>\n </div>\n ",
648
+ template: "<div>\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">{{'Tables.SelectColumns' | translate}}</h5>\n <button (click)=\"cancel()\"\n type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Cancel\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n <div class=\"modal-body pt-0\">\n <div class=\"row\">\n <div class=\"col-12\">\n <p [translate]=\"'Tables.SelectColumnHelp'\"></p>\n <p [translate]=\"'Tables.MoveColumnHelp'\"></p>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-4\">\n <select [formControl]=\"availableColumnsControl\" size=\"10\" class=\"form-select form-control\" multiple aria-label=\"multiple select example\">\n <ng-container *ngIf=\"columns\">\n <ng-container *ngFor=\"let column of columns | orderBy: ['title']\">\n <option class=\"text-wrap\" [value]=\"column.key\">{{column.title}}</option>\n </ng-container>\n </ng-container>\n </select>\n </div>\n <div class=\"col-4 d-flex justify-content-center align-items-center\">\n <div class=\"col-9\">\n <div>\n <button [disabled]=\"!(availableColumnsControl.value && availableColumnsControl.value.length)\" (click)=\"addColumns()\" type=\"button\" class=\"btn btn-primary btn-block\">\n <i class=\"fas fa-plus mr-2\"></i><span [translate]=\"'Tables.AddColumn'\"></span>\n </button>\n </div>\n <div class=\"mt-3\">\n <button [disabled]=\"!(selectedColumnsControl.value && selectedColumnsControl.value.length)\" (click)=\"removeColumns()\" type=\"button\" class=\"btn btn-secondary btn-block\">\n <i class=\"fas fa-minus mr-2\"></i><span [translate]=\"'Tables.RemoveColumn'\"></span>\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-4\">\n <select [formControl]=\"selectedColumnsControl\" size=\"10\" class=\"form-select form-control\" multiple aria-label=\"multiple select example\">\n <ng-container *ngIf=\"selectedColumns\">\n <ng-container *ngFor=\"let column of selectedColumns\">\n <option class=\"text-wrap\" [value]=\"column.key\">{{column.title}}</option>\n </ng-container>\n </ng-container>\n </select>\n <div class=\"d-flex justify-content-center align-items-center\">\n <div class=\"btn-group mt-4\">\n <button #moveUpButton (click)=\"moveUp()\" type=\"button\" class=\"btn btn-primary\">\n <i class=\"fas fa-chevron-up mr-2\"></i><span [translate]=\"'Tables.MoveUp'\"></span>\n </button>\n <button #moveDownButton (click)=\"moveDown()\" type=\"button\" class=\"btn btn-primary ml-2\">\n <i class=\"fas fa-chevron-down mr-2\"></i><span [translate]=\"'Tables.MoveDown'\"></span>\n </button>\n </div>\n </div>\n </div>\n </div>\n \n </div>\n <div class=\"modal-footer justify-content-end\">\n\n <button [disabled]=\"okButtonDisabled\" (click)=\"ok()\"\n type=\"button\" class=\"btn btn-primary\">\n <i *ngIf=\"changing\" class=\"fa fa-spinner fa-spin mr-1\"></i>\n {{'OK' | translate}}\n </button>\n <button [disabled]=\"cancelButtonDisabled\"\n (click)=\"cancel()\" type=\"button\" [ngClass]=\"cancelButtonClass\" data-dismiss=\"modal\">\n {{'Cancel' | translate}}\n </button>\n </div>\n </div>\n ",
633
649
  encapsulation: ViewEncapsulation.Emulated,
634
650
  styles: [`
635
651
  .form-select {
@@ -652,8 +668,7 @@ ColumnSelectorComponent.ctorParameters = () => [
652
668
  { type: Router },
653
669
  { type: ActivatedRoute },
654
670
  { type: BsModalRef },
655
- { type: ChangeDetectorRef },
656
- { type: TranslateService }
671
+ { type: ChangeDetectorRef }
657
672
  ];
658
673
  ColumnSelectorComponent.propDecorators = {
659
674
  columns: [{ type: Input }],
@@ -1748,113 +1763,141 @@ class AdvancedTableComponent {
1748
1763
  if (order && order.length) {
1749
1764
  // get order query expression
1750
1765
  const orderByStr = order.map((expr) => {
1751
- return tableColumns[expr.column].name + ' ' + expr.dir || 'asc';
1766
+ let columnIndex;
1767
+ if (self.columnOrdering === false) {
1768
+ columnIndex = expr.column;
1769
+ }
1770
+ else {
1771
+ // get the current column order (from colReorder)
1772
+ const columnOrder = self.dataTable.colReorder.order();
1773
+ // and match the dataTable index to the config columns index
1774
+ // expr.column should always be valid (e.g. in range), but perform a minor validation
1775
+ if (expr.column >= 0 && expr.column < columnOrder.length) {
1776
+ columnIndex = columnOrder[expr.column];
1777
+ }
1778
+ else {
1779
+ // use the first column as a fallback (won't happen, just for safety)
1780
+ columnIndex = 0;
1781
+ }
1782
+ }
1783
+ return tableColumns[columnIndex].name + ' ' + expr.dir || 'asc';
1752
1784
  }).join(',');
1753
1785
  // set order
1754
1786
  q.setParam('$orderby', orderByStr);
1755
1787
  }
1756
- // configure $select parameter
1757
- const select$$1 = self.config.columns.filter((column) => {
1758
- if (column.virtual === true) {
1759
- return false;
1788
+ self.stateLoadCallback(null, (state) => {
1789
+ // configure $select parameter
1790
+ const select$$1 = self.config.columns.filter((column) => {
1791
+ if (column.virtual === true) {
1792
+ return false;
1793
+ }
1794
+ if (column.optional === true) {
1795
+ if (state && state.columns) {
1796
+ const index = tableColumns.findIndex((tableColumn) => tableColumn.name === column.name);
1797
+ if (index >= 0) {
1798
+ return state.columns[index].visible;
1799
+ }
1800
+ }
1801
+ return false;
1802
+ }
1803
+ return true;
1804
+ }).map((column) => {
1805
+ if (column.property) {
1806
+ return column.name + ' as ' + column.property;
1807
+ }
1808
+ else {
1809
+ return column.name;
1810
+ }
1811
+ });
1812
+ q.select.apply(q, select$$1);
1813
+ // configure $filter
1814
+ if (queryParams.$filter && queryParams.$filter.length) {
1815
+ // set route filter
1816
+ const qParams = q.getParams();
1817
+ q.setParam('$filter', null);
1818
+ const expressions = [queryParams.$filter];
1819
+ if (qParams.$filter) {
1820
+ expressions.push('(' + qParams.$filter + ')');
1821
+ }
1822
+ q.filter(expressions.join(' and '));
1760
1823
  }
1761
- return true;
1762
- }).map((column) => {
1763
- if (column.property) {
1764
- return column.name + ' as ' + column.property;
1824
+ // check if query parameters contain filter
1825
+ if (queryParams.$expand && queryParams.$expand.length) {
1826
+ // set route $expand
1827
+ q.setParam('$expand', queryParams.$expand);
1765
1828
  }
1766
- else {
1767
- return column.name;
1829
+ else if (self.config && self.config.defaults && self.config.defaults.expand) {
1830
+ q.setParam('$expand', self.config.defaults.expand);
1768
1831
  }
1769
- });
1770
- q.select.apply(q, select$$1);
1771
- // configure $filter
1772
- if (queryParams.$filter && queryParams.$filter.length) {
1773
- // set route filter
1774
- const qParams = q.getParams();
1775
- q.setParam('$filter', null);
1776
- const expressions = [queryParams.$filter];
1777
- if (qParams.$filter) {
1778
- expressions.push('(' + qParams.$filter + ')');
1832
+ if (!q.getParams()['$orderby'] && self.config && self.config.defaults && self.config.defaults.orderBy) {
1833
+ q.setParam('$orderby', self.config.defaults.orderBy);
1779
1834
  }
1780
- q.filter(expressions.join(' and '));
1781
- }
1782
- // check if query parameters contain filter
1783
- if (queryParams.$expand && queryParams.$expand.length) {
1784
- // set route $expand
1785
- q.setParam('$expand', queryParams.$expand);
1786
- }
1787
- else if (self.config && self.config.defaults && self.config.defaults.expand) {
1788
- q.setParam('$expand', self.config.defaults.expand);
1789
- }
1790
- if (!q.getParams()['$orderby'] && self.config && self.config.defaults && self.config.defaults.orderBy) {
1791
- q.setParam('$orderby', self.config.defaults.orderBy);
1792
- }
1793
- if (self.config && self.config.defaults && self.config.defaults.groupBy) {
1794
- q.setParam('$groupby', self.config.defaults.groupBy);
1795
- }
1796
- // append default filter
1797
- if (self.config && self.config.defaults && self.config.defaults.filter) {
1798
- return self._advancedFilterValueProvider.asyncBuildFilter(self.config.defaults.filter).then((defaultFilterString) => {
1799
- if (defaultFilterString) {
1800
- const qParams = q.getParams();
1801
- q.setParam('$filter', null);
1802
- const expressions = [defaultFilterString];
1803
- if (qParams.$filter) {
1804
- expressions.push('(' + qParams.$filter + ')');
1805
- }
1806
- q.filter(expressions.join(' and '));
1807
- }
1808
- self.lastQueryParams = q.getParams();
1809
- return q.getList().then((items) => {
1810
- const dataSet = {
1811
- recordsTotal: items.total,
1812
- recordsFiltered: items.total,
1813
- data: items.value,
1814
- };
1815
- self._lastQueryTotalItems = items.total;
1816
- if (items.total === 0) {
1817
- self.resetEmptyTable();
1835
+ if (self.config && self.config.defaults && self.config.defaults.groupBy) {
1836
+ q.setParam('$groupby', self.config.defaults.groupBy);
1837
+ }
1838
+ // append default filter
1839
+ if (self.config && self.config.defaults && self.config.defaults.filter) {
1840
+ return self._advancedFilterValueProvider.asyncBuildFilter(self.config.defaults.filter).then((defaultFilterString) => {
1841
+ if (defaultFilterString) {
1842
+ const qParams = q.getParams();
1843
+ q.setParam('$filter', null);
1844
+ const expressions = [defaultFilterString];
1845
+ if (qParams.$filter) {
1846
+ expressions.push('(' + qParams.$filter + ')');
1847
+ }
1848
+ q.filter(expressions.join(' and '));
1818
1849
  }
1819
- // emit load event
1820
- self.load.emit(dataSet);
1821
- // return data
1822
- return fnCallback(dataSet);
1850
+ self.lastQueryParams = q.getParams();
1851
+ return q.getList().then((items) => {
1852
+ const dataSet = {
1853
+ recordsTotal: items.total,
1854
+ recordsFiltered: items.total,
1855
+ data: items.value,
1856
+ };
1857
+ self._lastQueryTotalItems = items.total;
1858
+ if (items.total === 0) {
1859
+ self.resetEmptyTable();
1860
+ }
1861
+ // emit load event
1862
+ self.load.emit(dataSet);
1863
+ // return data
1864
+ return fnCallback(dataSet);
1865
+ });
1866
+ }).catch((err) => {
1867
+ // log error to console
1868
+ console.error('TABLES', err);
1869
+ // show error
1870
+ self.toggleError(err);
1871
+ self._lastQueryTotalItems = 0;
1872
+ // by returning empty dataset
1873
+ self.load.emit(EMPTY_DATASET);
1874
+ return fnCallback(EMPTY_DATASET);
1823
1875
  });
1876
+ }
1877
+ self.lastQueryParams = q.getParams();
1878
+ q.getList().then((items) => {
1879
+ const dataSet = {
1880
+ recordsTotal: items.total,
1881
+ recordsFiltered: items.total,
1882
+ data: items.value,
1883
+ };
1884
+ self._lastQueryTotalItems = items.total;
1885
+ if (items.total === 0) {
1886
+ self.resetEmptyTable();
1887
+ }
1888
+ // emit load event
1889
+ self.load.emit(dataSet);
1890
+ // return data
1891
+ return fnCallback(dataSet);
1824
1892
  }).catch((err) => {
1825
1893
  // log error to console
1826
1894
  console.error('TABLES', err);
1827
1895
  // show error
1828
1896
  self.toggleError(err);
1829
- self._lastQueryTotalItems = 0;
1830
1897
  // by returning empty dataset
1831
1898
  self.load.emit(EMPTY_DATASET);
1832
1899
  return fnCallback(EMPTY_DATASET);
1833
1900
  });
1834
- }
1835
- self.lastQueryParams = q.getParams();
1836
- q.getList().then((items) => {
1837
- const dataSet = {
1838
- recordsTotal: items.total,
1839
- recordsFiltered: items.total,
1840
- data: items.value,
1841
- };
1842
- self._lastQueryTotalItems = items.total;
1843
- if (items.total === 0) {
1844
- self.resetEmptyTable();
1845
- }
1846
- // emit load event
1847
- self.load.emit(dataSet);
1848
- // return data
1849
- return fnCallback(dataSet);
1850
- }).catch((err) => {
1851
- // log error to console
1852
- console.error('TABLES', err);
1853
- // show error
1854
- self.toggleError(err);
1855
- // by returning empty dataset
1856
- self.load.emit(EMPTY_DATASET);
1857
- return fnCallback(EMPTY_DATASET);
1858
1901
  });
1859
1902
  },
1860
1903
  language: Object.assign({}, self.translator.transform('Tables.DataTable'), { emptyTable: ' ' }),
@@ -2221,12 +2264,8 @@ class AdvancedTableComponent {
2221
2264
  }
2222
2265
  // finally apply column order
2223
2266
  this.dataTable.colReorder.order(indexes, true);
2224
- if (this.selectable) {
2225
- // rebind onSelectionChange function
2226
- const tableElement = jQuery(this.table.nativeElement);
2227
- const elements = tableElement.find('input.s-row');
2228
- elements.off('click').on('click', this.onSelectionChange.bind(this));
2229
- }
2267
+ // simply redraw the table
2268
+ this.dataTable.draw();
2230
2269
  }
2231
2270
  });
2232
2271
  }
@@ -5075,6 +5114,7 @@ const selectTable = createSelector(getTablesState, (state, props) => {
5075
5114
  return state.tables[props.id];
5076
5115
  });
5077
5116
 
5117
+ // tslint:disable-next-line:directive-class-suffix
5078
5118
  class AdvancedTableState {
5079
5119
  constructor(table, store) {
5080
5120
  this.table = table;