@coolon/angular-ui-powerups 1.13.1 → 1.13.3

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 (72) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/bundles/coolon-angular-ui-powerups.umd.js +557 -540
  3. package/bundles/coolon-angular-ui-powerups.umd.js.map +1 -1
  4. package/bundles/coolon-angular-ui-powerups.umd.min.js +2 -2
  5. package/bundles/coolon-angular-ui-powerups.umd.min.js.map +1 -1
  6. package/coolon-angular-ui-powerups.metadata.json +1 -1
  7. package/esm2015/lib/components/components.module.js +3 -1
  8. package/esm2015/lib/components/components.module.js.map +1 -1
  9. package/esm2015/lib/components/components.module.metadata.json +1 -1
  10. package/esm2015/lib/components/components.module.ngfactory.js.map +1 -1
  11. package/esm2015/lib/components/index.js +1 -0
  12. package/esm2015/lib/components/index.js.map +1 -1
  13. package/esm2015/lib/components/index.metadata.json +1 -1
  14. package/esm2015/lib/components/scroll-container/scroll-container.component.js +1 -1
  15. package/esm2015/lib/components/scroll-container/scroll-container.component.js.map +1 -1
  16. package/esm2015/lib/components/scroll-container/scroll-container.component.metadata.json +1 -1
  17. package/esm2015/lib/components/table/cell-editors.js.map +1 -1
  18. package/esm2015/lib/components/table/cell-protal-ref.js +89 -0
  19. package/esm2015/lib/components/table/cell-protal-ref.js.map +1 -0
  20. package/esm2015/lib/components/table/cell-protal-ref.metadata.json +1 -0
  21. package/esm2015/lib/components/table/column-model.js +3 -105
  22. package/esm2015/lib/components/table/column-model.js.map +1 -1
  23. package/esm2015/lib/components/table/column-model.metadata.json +1 -1
  24. package/esm2015/lib/components/table/table-cell-renderer/table-cell-renderer.component.js +22 -9
  25. package/esm2015/lib/components/table/table-cell-renderer/table-cell-renderer.component.js.map +1 -1
  26. package/esm2015/lib/components/table/table-cell-renderer/table-cell-renderer.component.metadata.json +1 -1
  27. package/esm2015/lib/components/table/table-header-cell-renderer/table-header-cell-renderer.component.js +2 -1
  28. package/esm2015/lib/components/table/table-header-cell-renderer/table-header-cell-renderer.component.js.map +1 -1
  29. package/esm2015/lib/components/table/table-header-cell-renderer/table-header-cell-renderer.component.metadata.json +1 -1
  30. package/esm2015/lib/components/table/table-model.js +2 -1
  31. package/esm2015/lib/components/table/table-model.js.map +1 -1
  32. package/esm2015/lib/components/table/table-model.metadata.json +1 -1
  33. package/esm2015/lib/interaction/components/popup-interaction-context/popup-interaction-context.component.js +23 -7
  34. package/esm2015/lib/interaction/components/popup-interaction-context/popup-interaction-context.component.js.map +1 -1
  35. package/esm2015/lib/interaction/components/popup-interaction-context/popup-interaction-context.component.metadata.json +1 -1
  36. package/esm2015/lib/place/components/place-outlet/place-outlet.component.js +2 -2
  37. package/esm2015/lib/place/components/place-outlet/place-outlet.component.js.map +1 -1
  38. package/esm2015/lib/place/components/place-outlet/place-outlet.component.metadata.json +1 -1
  39. package/esm5/lib/components/components.module.js +3 -1
  40. package/esm5/lib/components/components.module.js.map +1 -1
  41. package/esm5/lib/components/components.module.ngfactory.js.map +1 -1
  42. package/esm5/lib/components/index.js +1 -0
  43. package/esm5/lib/components/index.js.map +1 -1
  44. package/esm5/lib/components/scroll-container/scroll-container.component.js +1 -1
  45. package/esm5/lib/components/scroll-container/scroll-container.component.js.map +1 -1
  46. package/esm5/lib/components/table/cell-editors.js.map +1 -1
  47. package/esm5/lib/components/table/cell-protal-ref.js +113 -0
  48. package/esm5/lib/components/table/cell-protal-ref.js.map +1 -0
  49. package/esm5/lib/components/table/column-model.js +4 -129
  50. package/esm5/lib/components/table/column-model.js.map +1 -1
  51. package/esm5/lib/components/table/table-cell-renderer/table-cell-renderer.component.js +31 -16
  52. package/esm5/lib/components/table/table-cell-renderer/table-cell-renderer.component.js.map +1 -1
  53. package/esm5/lib/components/table/table-header-cell-renderer/table-header-cell-renderer.component.js +2 -1
  54. package/esm5/lib/components/table/table-header-cell-renderer/table-header-cell-renderer.component.js.map +1 -1
  55. package/esm5/lib/components/table/table-model.js +2 -1
  56. package/esm5/lib/components/table/table-model.js.map +1 -1
  57. package/esm5/lib/interaction/components/popup-interaction-context/popup-interaction-context.component.js +23 -7
  58. package/esm5/lib/interaction/components/popup-interaction-context/popup-interaction-context.component.js.map +1 -1
  59. package/esm5/lib/place/components/place-outlet/place-outlet.component.js +2 -2
  60. package/esm5/lib/place/components/place-outlet/place-outlet.component.js.map +1 -1
  61. package/fesm2015/coolon-angular-ui-powerups.js +527 -511
  62. package/fesm2015/coolon-angular-ui-powerups.js.map +1 -1
  63. package/fesm5/coolon-angular-ui-powerups.js +556 -538
  64. package/fesm5/coolon-angular-ui-powerups.js.map +1 -1
  65. package/lib/components/index.d.ts +1 -0
  66. package/lib/components/table/cell-protal-ref.d.ts +53 -0
  67. package/lib/components/table/column-model.d.ts +2 -48
  68. package/lib/components/table/table-cell-renderer/table-cell-renderer.component.d.ts +8 -3
  69. package/lib/components/table/table-header-cell-renderer/table-header-cell-renderer.component.d.ts +2 -1
  70. package/lib/components/table/table-model.d.ts +2 -1
  71. package/lib/interaction/components/popup-interaction-context/popup-interaction-context.component.d.ts +3 -2
  72. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { __decorate, __metadata, __param, __awaiter } from 'tslib';
2
2
  import { DOCUMENT, CommonModule, Location } from '@angular/common';
3
- import { ElementRef, Inject, Input, HostListener, Directive, NgZone, ɵɵdefineInjectable, ɵɵinject, Injectable, NgModule, HostBinding, Component, InjectionToken, Injector, ComponentFactoryResolver, ViewContainerRef, ViewChild, ViewChildren, QueryList, Optional, EventEmitter, Output, ContentChild, TemplateRef, Self, ChangeDetectorRef, ContentChildren, SkipSelf } from '@angular/core';
3
+ import { ElementRef, Inject, Input, HostListener, Directive, NgZone, ɵɵdefineInjectable, ɵɵinject, Injectable, NgModule, HostBinding, Component, InjectionToken, Injector, ComponentFactoryResolver, ViewContainerRef, ViewChild, ViewChildren, QueryList, Optional, SkipSelf, EventEmitter, Output, ContentChild, TemplateRef, Self, ChangeDetectorRef, ContentChildren } from '@angular/core';
4
4
  import { FormsModule } from '@angular/forms';
5
5
  import { MatFormFieldModule } from '@angular/material/form-field';
6
6
  import { MatInputModule } from '@angular/material/input';
@@ -8,6 +8,7 @@ import { MatSelectModule } from '@angular/material/select';
8
8
  import { MatTabsModule, MatTabGroup, MAT_TABS_CONFIG } from '@angular/material/tabs';
9
9
  import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
10
10
  import { ComponentPortal, PortalModule, TemplatePortal } from '@angular/cdk/portal';
11
+ import { CdkScrollableModule } from '@angular/cdk/scrolling';
11
12
  import { MatButtonModule } from '@angular/material/button';
12
13
  import { MatCheckboxModule } from '@angular/material/checkbox';
13
14
  import { MatIconModule } from '@angular/material/icon';
@@ -18,7 +19,7 @@ import { MatDialogModule, MatDialog, MatDialogConfig, MAT_DIALOG_DEFAULT_OPTIONS
18
19
  import { RouterModule, UrlSegment, Router, UrlSerializer, NavigationStart, NavigationEnd, NavigationError, NavigationCancel, RouterOutlet } from '@angular/router';
19
20
  import ___default, { isEqual, isNil } from 'lodash';
20
21
  import { assert as assert$1, lang as lang$1, Opts, Klass } from '@coolon/typescript-utilities';
21
- import { Overlay } from '@angular/cdk/overlay';
22
+ import { Overlay, CdkScrollable } from '@angular/cdk/overlay';
22
23
  import { Memoize } from '@typescript-plus/fast-memoize-decorator/dist/src';
23
24
  import produce from 'immer';
24
25
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@@ -1129,26 +1130,34 @@ AddItemInteractionContextComponent = __decorate([
1129
1130
  ], AddItemInteractionContextComponent);
1130
1131
 
1131
1132
  let PopupInteractionContextComponent = class PopupInteractionContextComponent extends DisposableComponent {
1132
- constructor(_element, _overlay) {
1133
+ constructor(_element, _overlay, scrollable) {
1133
1134
  super();
1134
1135
  this._element = _element;
1135
1136
  this._overlay = _overlay;
1136
1137
  this.outputPortal = new ComponentPortal(InPlaceInteractionContextComponent);
1137
1138
  this.anchorX = 'start';
1138
1139
  this.anchorY = 'bottom';
1140
+ this.scrollContainers = scrollable ? [scrollable] : [];
1139
1141
  }
1140
1142
  get active() {
1141
1143
  return this.isActive();
1142
1144
  }
1143
1145
  startActivity(activityType, data) {
1146
+ // console.log({ element: this._element });
1147
+ const self = this;
1144
1148
  const overlayRef = this._overlay.create({
1145
1149
  hasBackdrop: false,
1146
1150
  panelClass: 'aup-popup-interaction-panel',
1147
1151
  positionStrategy: this._overlay.position()
1148
1152
  .flexibleConnectedTo(this._element)
1153
+ .withPush(true)
1149
1154
  .withPositions(this.computePositions())
1150
1155
  .withGrowAfterOpen(true)
1156
+ .withScrollableContainers(self.scrollContainers) // this isn't working. sigh.
1151
1157
  });
1158
+ const subs = this.scrollContainers.map(sc => sc.elementScrolled().subscribe(() => {
1159
+ overlayRef.updatePosition();
1160
+ }));
1152
1161
  const componentRef = overlayRef.attach(this.outputPortal);
1153
1162
  this.interactionContext = componentRef.instance;
1154
1163
  return new Promise((resolve, reject) => {
@@ -1157,7 +1166,13 @@ let PopupInteractionContextComponent = class PopupInteractionContextComponent ex
1157
1166
  this.interactionContext.startActivity(activityType, data)
1158
1167
  .then(resolve)
1159
1168
  .catch(reject)
1160
- .finally(() => overlayRef.dispose());
1169
+ .finally(() => {
1170
+ subs.forEach(s => s.unsubscribe());
1171
+ overlayRef.dispose();
1172
+ });
1173
+ setTimeout(() => {
1174
+ overlayRef.updatePosition();
1175
+ });
1161
1176
  });
1162
1177
  });
1163
1178
  }
@@ -1184,7 +1199,8 @@ let PopupInteractionContextComponent = class PopupInteractionContextComponent ex
1184
1199
  };
1185
1200
  PopupInteractionContextComponent.ctorParameters = () => [
1186
1201
  { type: ElementRef },
1187
- { type: Overlay }
1202
+ { type: Overlay },
1203
+ { type: CdkScrollable, decorators: [{ type: Optional }, { type: SkipSelf }] }
1188
1204
  ];
1189
1205
  __decorate([
1190
1206
  HostBinding('class.interaction-active'),
@@ -1205,7 +1221,8 @@ PopupInteractionContextComponent = __decorate([
1205
1221
  template: "<ng-content></ng-content>\n",
1206
1222
  styles: [":host{display:inline}:host.interaction-active{background:rgba(0,0,0,.05)}"]
1207
1223
  }),
1208
- __metadata("design:paramtypes", [ElementRef, Overlay])
1224
+ __param(2, Optional()), __param(2, SkipSelf()),
1225
+ __metadata("design:paramtypes", [ElementRef, Overlay, CdkScrollable])
1209
1226
  ], PopupInteractionContextComponent);
1210
1227
 
1211
1228
  let InteractionContextTriggerFor = class InteractionContextTriggerFor extends GarbageCollector {
@@ -2022,7 +2039,7 @@ let ScrollContainerComponent = class ScrollContainerComponent {
2022
2039
  ScrollContainerComponent = __decorate([
2023
2040
  Component({
2024
2041
  selector: 'aup-scroll-container',
2025
- template: "<div class=\"container\">\n <ng-content></ng-content>\n</div>\n",
2042
+ template: "<div class=\"container\" cdkScrollable>\n <ng-content></ng-content>\n</div>\n",
2026
2043
  styles: [":host{display:flex;flex-direction:column;min-height:0;align-items:stretch}.container{display:flex;flex-direction:column;flex:1;flex-basis:0;overflow-y:scroll;align-items:stretch}"]
2027
2044
  }),
2028
2045
  __metadata("design:paramtypes", [])
@@ -2145,6 +2162,93 @@ SwitchCaseComponent = __decorate([
2145
2162
  __metadata("design:paramtypes", [ChangeDetectorRef])
2146
2163
  ], SwitchCaseComponent);
2147
2164
 
2165
+ const HEADER_CELL_RENDERER_PORTAL = Symbol('aup-cell-header-renderer-component-ref');
2166
+ const CELL_RENDERER_PORTAL = Symbol('aup-cell-renderer-component-ref');
2167
+ const CELL_EDITOR_PORTAL = Symbol('aup-cell-editor-component-ref');
2168
+ const PORTAL_RENDERER_COMPONENT = Symbol('aup-cell-renderer-portal-component');
2169
+ const PORTAL_EDITOR_COMPONENT = Symbol('aup-cell-editor-portal-component');
2170
+ class CellPortalRef {
2171
+ constructor() {
2172
+ }
2173
+ }
2174
+ class CellHeaderPortalRef extends CellPortalRef {
2175
+ constructor(componentType, initialiseHeader) {
2176
+ super();
2177
+ this.componentType = componentType;
2178
+ this.initialiseHeader = initialiseHeader;
2179
+ }
2180
+ initialiseHost(host, columnModel) {
2181
+ assert$1.isTruthy(host);
2182
+ host[HEADER_CELL_RENDERER_PORTAL] = new ComponentPortal(this.componentType);
2183
+ }
2184
+ onPortalAttached(host, portalComponent) {
2185
+ this.initialiseHeader(portalComponent, host.column);
2186
+ }
2187
+ }
2188
+ class CellRendererPortalRef extends CellPortalRef {
2189
+ }
2190
+ class ComponentCellRendererPortalRef extends CellRendererPortalRef {
2191
+ constructor(componentType, updateComponent) {
2192
+ super();
2193
+ this.componentType = componentType;
2194
+ this.updateComponent = updateComponent;
2195
+ }
2196
+ initialiseHost(host, columnModel) {
2197
+ host[CELL_RENDERER_PORTAL] = new ComponentPortal(this.componentType);
2198
+ }
2199
+ onPortalAttached(host, portalComponent) {
2200
+ host[PORTAL_RENDERER_COMPONENT] = portalComponent;
2201
+ this.updateComponent(portalComponent, host.getRowData());
2202
+ }
2203
+ pushState(host) {
2204
+ if (host[PORTAL_RENDERER_COMPONENT]) {
2205
+ this.updateComponent(host[PORTAL_RENDERER_COMPONENT], host.getRowData());
2206
+ }
2207
+ }
2208
+ }
2209
+ class CellEditorPortalRef extends CellPortalRef {
2210
+ constructor(componentType, initialiseEditorSession) {
2211
+ super();
2212
+ this.componentType = componentType;
2213
+ this.initialiseEditorSession = initialiseEditorSession;
2214
+ }
2215
+ initialiseHost(host, columnModel) {
2216
+ assert$1.isTruthy(host);
2217
+ host[CELL_EDITOR_PORTAL] = new ComponentPortal(this.componentType);
2218
+ }
2219
+ // @Trace()
2220
+ onPortalAttached(host, portalComponent) {
2221
+ host[PORTAL_EDITOR_COMPONENT] = portalComponent;
2222
+ this.initialiseEditorSession(portalComponent, host.editSession);
2223
+ }
2224
+ }
2225
+ class TemplateCellRendererPortalRef extends CellRendererPortalRef {
2226
+ constructor() {
2227
+ super();
2228
+ }
2229
+ registerPortal(templateRef, viewContainer, fillCell, padChild) {
2230
+ this.templateRef = templateRef;
2231
+ this.viewContainer = viewContainer;
2232
+ this.fillCell = fillCell;
2233
+ this.padChild = padChild;
2234
+ }
2235
+ initialiseHost(host, columnModel) {
2236
+ assert$1.isTruthy(host);
2237
+ }
2238
+ // @Trace()
2239
+ onPortalAttached(host, portalComponent) {
2240
+ // don't care
2241
+ }
2242
+ pushState(host) {
2243
+ host[CELL_RENDERER_PORTAL] = this.createPortal(host.getRowData());
2244
+ host.fillCell = this.fillCell;
2245
+ host.padChild = this.padChild;
2246
+ }
2247
+ createPortal(data) {
2248
+ return new TemplatePortal(this.templateRef, this.viewContainer, Object.assign(Object.assign({}, (data)), { $implicit: data.row }));
2249
+ }
2250
+ }
2251
+
2148
2252
  let DefaultCellRendererComponent = class DefaultCellRendererComponent {
2149
2253
  constructor() {
2150
2254
  }
@@ -2300,573 +2404,391 @@ SelectHeaderCellRendererComponent = __decorate([
2300
2404
  __metadata("design:paramtypes", [])
2301
2405
  ], SelectHeaderCellRendererComponent);
2302
2406
 
2303
- var TableModel_1;
2304
- // export type StringPropertiesOf<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T];
2305
- // export type NumberPropertiesOf<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T];
2306
- /**
2307
- * Example:
2308
- * @example
2309
- * const model = TableModel.fromList(heroList, table => {
2310
- * table.pluck("firstName");
2311
- * table.pluck("lastName");
2312
- * table.addCustomColumn("fullName", hero => `${hero.firstName} ${hero.lastName}`);
2313
- * });
2314
- *
2315
- * Editable tables
2316
- * @example
2317
- * const saveCommand = UnaryCommand.create((form: Form<Hero>) => {
2318
- * if (form.validate()) {
2319
- * // normal form save stuff
2320
- * return true; // finish editing
2321
- * }
2322
- * return false; // continue editiing
2323
- * }
2324
- * const colorsNames: ListModel<string> = ...;
2325
- * const model = TableModel.fromList(heroList, table => {
2326
- * table.pluck("firstName").cellEditor(StringInputComponent); <-- interface CellEditor { valueModel: FormValueModel<string> | ValueModel<string>; }
2327
- * table.pluck("lastName").cellEditor(StringInputComponent, {
2328
- * validators: [Validator.present("We need a last name")]
2329
- * });
2330
- * table.pluck("age").cellEditor(NumberInputComponent);
2331
- * table.pluck("favoriteColor").cellEditor(SelectInputComponent, {
2332
- * initialiseComponent(component: SelectInputComponent) {
2333
- * selectInput.optionsModel = colorsNames; // <- initialise our component
2334
- * }
2335
- * });
2336
- * table.addEditControls(saveCommand); // <- required to enable editing
2337
- * });
2338
- *
2339
- * Selection models
2340
- * @example
2341
- * const model = TableModel.fromList(heroList, table => {
2342
- * table.addSelectionColumn(selectionModel); // <- can be single or multiple selection model
2343
- * table.pluck("firstName");
2344
- * table.pluck("lastName");
2345
- * });
2346
- *
2347
- * Custom cell renderers and editors
2348
- * @example
2349
- * const model = TableModel.fromList(heroList, table => {
2350
- * table.pluck("favoriteColor")
2351
- * .cellHeaderRenderer(CellHeaderRendererComponent, (component, column) => {
2352
- * // configure your component with what ever you need.
2353
- * });
2354
- * .cellRenderer(CellRendererComponent) // <-- interface CellEditor { value: string; }
2355
- * .cellEditor(CellEditorComponent.); // <-- interface CellEditor { valueModel: FormValueModel<string> | ValueModel<string>; }
2356
- * table.addCustomColumn("fullName", hero => `${hero.firstName} ${hero.lastName}`);
2357
- * });
2358
- *
2359
- * I18n
2360
- * @example
2361
- * [table.yml]
2362
- * table:
2363
- * columns(ColumnTextProperties[]):
2364
- * firstName:
2365
- * headerText: "First Name"
2366
- * fullName:
2367
- * headerText: "Full Name"
2368
- *
2369
- * const model = TableModel.fromList(heroList, table => {
2370
- * table.pluck("favoriteColor").cellRenderer(...).cellEditor(...);
2371
- * table.addCustomColumn("fullName", hero => `${hero.firstName} ${hero.lastName}`);
2372
- *
2373
- * table.columnTextProperties(I18n.table.columns); // <- configures all columns
2374
- * });
2375
- */
2376
- let TableModel = TableModel_1 = class TableModel {
2377
- constructor(sourceOfTruth) {
2378
- this.sourceOfTruth = sourceOfTruth;
2379
- this._garbage = new GarbageCollector();
2380
- this._columns = new MutableListModel();
2381
- this._editorSessions = new MutableListModel();
2382
- this._createForm = (row) => new Form();
2383
- this.identityOf = sourceOfTruth.identityOf;
2384
- const { chain, valueOf, before, when, after, observe, switchOn } = Dsl.disposeWith(this._garbage);
2385
- this._columnsById = chain(this._columns).indexBy('columnId');
2386
- this._rowsBeingEdited = new MutableListModel([], {
2387
- identifiedWith: this.identityOf
2407
+ const noop = () => {
2408
+ };
2409
+ const ɵ0 = noop;
2410
+ class ColumnModel {
2411
+ constructor(columnId, defaults) {
2412
+ this.columnId = columnId;
2413
+ this.defaults = defaults;
2414
+ this.cellHeaderRenderer(DefaultHeaderCellRendererComponent, (component, column) => {
2415
+ component.headerText = column.getHeaderText();
2388
2416
  });
2389
- this._editorSessionByRowId = chain(this._editorSessions).indexBy('rowId');
2390
- this.editing = chain(this._editorSessions).count().isGreaterThan(0);
2391
- this.dataSource = chain(this.sourceOfTruth).replaceAll(this.rowsBeingEdited);
2392
- }
2393
- static fromList(sourceOfTruth, builder) {
2394
- const model = new TableModel_1(sourceOfTruth);
2395
- builder(model);
2396
- return model;
2397
2417
  }
2398
- get rowsBeingEdited() {
2399
- return this._rowsBeingEdited.readonly;
2418
+ getHeaderText() {
2419
+ var _a;
2420
+ return ((_a = this.getColumnTextProperties()) === null || _a === void 0 ? void 0 : _a.headerText()) || this.getDefaultHeaderText();
2400
2421
  }
2401
- getTrackByFunction() {
2402
- return (index, item) => {
2403
- return this.identityOf ? this.identityOf(item) : index;
2404
- };
2422
+ getDefaultHeaderText() {
2423
+ return this.columnId;
2405
2424
  }
2406
- get columns() {
2407
- return this._columns.readonly;
2425
+ getColumnTextProperties() {
2426
+ return this._columnTextProperties || this.defaults.getColumnTextProperties(this);
2408
2427
  }
2409
- pluck(property) {
2410
- return this.addColumn(new PropertyColumnModel(property, this));
2428
+ textProperties(columnTextProperties) {
2429
+ this._columnTextProperties = columnTextProperties;
2430
+ return this;
2411
2431
  }
2412
- pluckList(property) {
2413
- return this.addColumn(new ListPropertyColumnModel(property, this));
2432
+ configureHeaderRenderer(config) {
2433
+ this._columnHeaderPortalRef = config;
2414
2434
  }
2415
- addSelectionColumn(selectionModel) {
2416
- return this.addColumn(new SelectionColumnModel('selection', this, selectionModel));
2435
+ configureCellRenderer(config) {
2436
+ this._cellRendererPortalRef = config;
2417
2437
  }
2418
- addEditControls(saveCommand) {
2419
- this.saveCommand = saveCommand;
2420
- return this.addColumn(new EditorControlColumnModel('editControls', saveCommand, this));
2438
+ configureCellEditor(cellEditor) {
2439
+ this._cellEditorPortalRef = cellEditor;
2421
2440
  }
2422
- addCustomColumn(columnId, dataAccessor) {
2423
- return this.addColumn(new CustomValueColumnModel(columnId, this, dataAccessor));
2441
+ cellHeaderRenderer(componentType, initialiser) {
2442
+ this.configureHeaderRenderer(new CellHeaderPortalRef(componentType, initialiser));
2443
+ return this;
2424
2444
  }
2425
- addTemplateColumn(columnId) {
2426
- return this.addColumn(new CustomTemplateColumnModel(columnId, this));
2445
+ hasEditorPortal() {
2446
+ return !!this._cellEditorPortalRef;
2427
2447
  }
2428
- useFormFactory(factory) {
2429
- this._createForm = factory;
2430
- return this;
2448
+ attachHeaderCell(host) {
2449
+ this._columnHeaderPortalRef.initialiseHost(host, this);
2431
2450
  }
2432
- addColumn(column) {
2433
- if (this._columnsById.get(column.columnId)) {
2434
- lang.illegalState(`Column with id=${column.columnId} already exists`);
2435
- }
2436
- else {
2437
- this._columns.push(column);
2451
+ attachCell(host) {
2452
+ this._cellRendererPortalRef.initialiseHost(host, this);
2453
+ if (this.hasEditorPortal()) {
2454
+ this._cellEditorPortalRef.initialiseHost(host, this);
2438
2455
  }
2439
- return column;
2440
2456
  }
2441
- columnTextProperties(columnTextProperties) {
2442
- this._columnTextPropertiesLookup = columnTextProperties;
2457
+ onHeaderAttached(host, component) {
2458
+ this._columnHeaderPortalRef.onPortalAttached(host, component);
2443
2459
  }
2444
- getColumnTextProperties(column) {
2445
- const factory = this._columnTextPropertiesLookup ? this._columnTextPropertiesLookup[column.columnId] : undefined;
2446
- return factory ? factory() : undefined;
2447
- }
2448
- startEditSession(row) {
2449
- const rowId = this.identityOf(row);
2450
- if (this._rowsBeingEdited.query().indexOf(row) > -1) {
2451
- return lang.illegalState(`Row with id=${rowId} already being edited`);
2452
- }
2453
- else {
2454
- const editSession = new EditSession(rowId, row, this._createForm(row), this.saveCommand);
2455
- const { when } = Dsl.disposeWith(editSession);
2456
- when.valueOf(editSession.liveRowValue).changes((editedValue) => {
2457
- this._rowsBeingEdited.replaceOrPush(editedValue);
2458
- }, { initialValue: 'triggerChangeUnlessNil' });
2459
- this._editorSessions.push(editSession);
2460
- editSession.onDispose(() => {
2461
- this._rowsBeingEdited.remove(editSession.liveRowValue.value);
2462
- this._editorSessions.remove(editSession);
2463
- });
2464
- return editSession;
2465
- }
2466
- }
2467
- getEditSessionFor(row) {
2468
- return this._editorSessionByRowId.get(this.identityOf(row));
2469
- }
2470
- cancelAllEditorSessions() {
2471
- this._editorSessions.runInTransaction((draft) => {
2472
- this._rowsBeingEdited.runInTransaction(() => {
2473
- draft.value.forEach(session => session.dispose());
2474
- });
2475
- });
2476
- }
2477
- };
2478
- TableModel.ctorParameters = () => [
2479
- { type: ListModel }
2480
- ];
2481
- TableModel = TableModel_1 = __decorate([
2482
- TrackExternal.Strategy(new TrackExternal.OneTimeBinding()),
2483
- __metadata("design:paramtypes", [ListModel])
2484
- ], TableModel);
2485
-
2486
- let TableCellRendererComponent = class TableCellRendererComponent {
2487
- constructor() {
2488
- this.defaultClassNames = 'aup-cell-renderer';
2489
- this.fillCell = false;
2490
- this.padChild = false;
2491
- this.editRowCommand = Command.create(() => {
2492
- this.tableModel.startEditSession(this.row);
2493
- });
2494
- }
2495
- ngOnInit() {
2496
- this.column.attachCell(this);
2497
- }
2498
- hasActiveEditor() {
2499
- return !!this.editSession && !!this.column.hasEditorPortal();
2500
- }
2501
- initialiseRenderer(instance) {
2502
- this.column.onRendererAttached(this, instance);
2503
- }
2504
- initialiseEditor(instance) {
2505
- this.column.onEditorAttached(this, instance);
2460
+ onRendererAttached(host, component) {
2461
+ this._cellRendererPortalRef.onPortalAttached(host, component);
2506
2462
  }
2507
2463
  // @Trace()
2508
- ngOnChanges(changes) {
2509
- this.column.updatePortalContent(this);
2510
- }
2511
- getRendererPortal() {
2512
- return this[CELL_RENDERER_PORTAL];
2513
- }
2514
- getEditorPortal() {
2515
- return this[CELL_EDITOR_PORTAL];
2464
+ onEditorAttached(host, component) {
2465
+ this._cellEditorPortalRef.onPortalAttached(host, component);
2516
2466
  }
2517
- getRowData() {
2518
- return {
2519
- row: this.row,
2520
- editSession: this.editSession,
2521
- editRowCommand: this.editRowCommand
2522
- };
2467
+ updatePortalContent(host) {
2468
+ this._cellRendererPortalRef.pushState(host);
2523
2469
  }
2524
- };
2525
- __decorate([
2526
- Input(),
2527
- __metadata("design:type", Object)
2528
- ], TableCellRendererComponent.prototype, "row", void 0);
2529
- __decorate([
2530
- Input(),
2531
- __metadata("design:type", ColumnModel)
2532
- ], TableCellRendererComponent.prototype, "column", void 0);
2533
- __decorate([
2534
- Input(),
2535
- __metadata("design:type", EditSession)
2536
- ], TableCellRendererComponent.prototype, "editSession", void 0);
2537
- __decorate([
2538
- Input(),
2539
- __metadata("design:type", TableModel)
2540
- ], TableCellRendererComponent.prototype, "tableModel", void 0);
2541
- __decorate([
2542
- HostBinding('class'),
2543
- __metadata("design:type", Object)
2544
- ], TableCellRendererComponent.prototype, "defaultClassNames", void 0);
2545
- __decorate([
2546
- HostBinding('class.fillCell'),
2547
- __metadata("design:type", Object)
2548
- ], TableCellRendererComponent.prototype, "fillCell", void 0);
2470
+ }
2549
2471
  __decorate([
2550
- HostBinding('class.padChild'),
2551
- __metadata("design:type", Object)
2552
- ], TableCellRendererComponent.prototype, "padChild", void 0);
2472
+ Memoize(),
2473
+ __metadata("design:type", Function),
2474
+ __metadata("design:paramtypes", []),
2475
+ __metadata("design:returntype", String)
2476
+ ], ColumnModel.prototype, "getHeaderText", null);
2553
2477
  __decorate([
2554
- Trace(),
2478
+ Memoize(),
2555
2479
  __metadata("design:type", Function),
2556
- __metadata("design:paramtypes", [Object]),
2557
- __metadata("design:returntype", void 0)
2558
- ], TableCellRendererComponent.prototype, "initialiseEditor", null);
2559
- TableCellRendererComponent = __decorate([
2560
- Component({
2561
- selector: 'aup-table-cell-renderer',
2562
- template: "<ng-container *ngIf=\"!hasActiveEditor()\" [cdkPortalOutlet]=\"getRendererPortal()\" (attached)=\"initialiseRenderer($event.instance)\"></ng-container>\n<ng-container *ngIf=\"hasActiveEditor()\" [cdkPortalOutlet]=\"getEditorPortal()\" (attached)=\"initialiseEditor($event.instance)\"></ng-container>\n",
2563
- styles: [""]
2564
- }),
2565
- __metadata("design:paramtypes", [])
2566
- ], TableCellRendererComponent);
2567
-
2568
- const HEADER_CELL_RENDERER_PORTAL = Symbol('aup-cell-header-renderer-component-ref');
2569
- const CELL_RENDERER_PORTAL = Symbol('aup-cell-renderer-component-ref');
2570
- const CELL_EDITOR_PORTAL = Symbol('aup-cell-editor-component-ref');
2571
- const PORTAL_RENDERER_COMPONENT = Symbol('aup-cell-renderer-portal-component');
2572
- const PORTAL_EDITOR_COMPONENT = Symbol('aup-cell-editor-portal-component');
2573
- const noop = () => {
2574
- };
2575
- const ɵ0 = noop;
2576
- class CellPortalRef {
2577
- constructor() {
2480
+ __metadata("design:paramtypes", []),
2481
+ __metadata("design:returntype", Object)
2482
+ ], ColumnModel.prototype, "getColumnTextProperties", null);
2483
+ class PropertyColumnModel extends ColumnModel {
2484
+ constructor(property, defaults) {
2485
+ super(property.toString(), defaults);
2486
+ this.property = property;
2487
+ this._format = (value) => value;
2488
+ this.cellRenderer(DefaultCellRendererComponent);
2578
2489
  }
2579
- }
2580
- class CellHeaderPortalRef extends CellPortalRef {
2581
- constructor(componentType, initialiseHeader) {
2582
- super();
2583
- this.componentType = componentType;
2584
- this.initialiseHeader = initialiseHeader;
2490
+ cellRenderer(componentType) {
2491
+ this.configureCellRenderer(new ComponentCellRendererPortalRef(componentType, (component, rowData) => {
2492
+ component.value = this._format(rowData.row[this.property]);
2493
+ }));
2494
+ return this;
2585
2495
  }
2586
- initialiseHost(host, columnModel) {
2587
- assert$1.isTruthy(host);
2588
- host[HEADER_CELL_RENDERER_PORTAL] = new ComponentPortal(this.componentType);
2496
+ cellEditor(editor, validatorsOrInitialiser, initialiseComponent) {
2497
+ const validators = Array.isArray(validatorsOrInitialiser) ? validatorsOrInitialiser : undefined;
2498
+ const initialiser = ___default.isFunction(validatorsOrInitialiser) ? validatorsOrInitialiser : initialiseComponent;
2499
+ this.configureCellEditor(new CellEditorPortalRef(editor, (component, editSession) => {
2500
+ const formValueModel = editSession.form.pluck(this.property);
2501
+ if (validators) {
2502
+ formValueModel.validateUsing(validators);
2503
+ }
2504
+ component.valueModel = formValueModel;
2505
+ if (initialiser) {
2506
+ initialiser(component);
2507
+ }
2508
+ }));
2509
+ return this;
2589
2510
  }
2590
- onPortalAttached(host, portalComponent) {
2591
- this.initialiseHeader(portalComponent, host.column);
2511
+ format(formatter) {
2512
+ assert$1.isFunction(formatter);
2513
+ this._format = formatter;
2514
+ return this;
2592
2515
  }
2593
2516
  }
2594
- class CellRendererPortalRef extends CellPortalRef {
2595
- }
2596
- class ComponentCellRendererPortalRef extends CellRendererPortalRef {
2597
- constructor(componentType, updateComponent) {
2598
- super();
2599
- this.componentType = componentType;
2600
- this.updateComponent = updateComponent;
2517
+ class ListPropertyColumnModel extends ColumnModel {
2518
+ constructor(property, defaults) {
2519
+ super(property.toString(), defaults);
2520
+ this.property = property;
2521
+ this._format = (value) => value.map(v => v === null || v === void 0 ? void 0 : v.toString()).join(', ');
2522
+ this.cellRenderer(DefaultCellRendererComponent);
2601
2523
  }
2602
- initialiseHost(host, columnModel) {
2603
- host[CELL_RENDERER_PORTAL] = new ComponentPortal(this.componentType);
2524
+ cellRenderer(componentType) {
2525
+ this.configureCellRenderer(new ComponentCellRendererPortalRef(componentType, (component, rowData) => {
2526
+ component.value = this._format(rowData.row[this.property]);
2527
+ }));
2528
+ return this;
2604
2529
  }
2605
- onPortalAttached(host, portalComponent) {
2606
- host[PORTAL_RENDERER_COMPONENT] = portalComponent;
2607
- this.updateComponent(portalComponent, host.getRowData());
2530
+ cellEditor(editor, validatorsOrInitialiser, initialiseComponent) {
2531
+ const validators = Array.isArray(validatorsOrInitialiser) ? validatorsOrInitialiser : undefined;
2532
+ const initialiser = ___default.isFunction(validatorsOrInitialiser) ? validatorsOrInitialiser : initialiseComponent;
2533
+ this.configureCellEditor(new CellEditorPortalRef(editor, (component, editSession) => {
2534
+ const formListModel = editSession.form.pluckList(this.property);
2535
+ if (validators) {
2536
+ formListModel.validateUsing(validators);
2537
+ }
2538
+ component.listModel = formListModel;
2539
+ if (initialiser) {
2540
+ initialiser(component);
2541
+ }
2542
+ }));
2543
+ return this;
2608
2544
  }
2609
- pushState(host) {
2610
- if (host[PORTAL_RENDERER_COMPONENT]) {
2611
- this.updateComponent(host[PORTAL_RENDERER_COMPONENT], host.getRowData());
2612
- }
2545
+ format(formatter) {
2546
+ assert$1.isFunction(formatter);
2547
+ this._format = formatter;
2548
+ return this;
2613
2549
  }
2614
2550
  }
2615
- class CellEditorPortalRef extends CellPortalRef {
2616
- constructor(componentType, initialiseEditorSession) {
2617
- super();
2618
- this.componentType = componentType;
2619
- this.initialiseEditorSession = initialiseEditorSession;
2620
- }
2621
- initialiseHost(host, columnModel) {
2622
- assert$1.isTruthy(host);
2623
- host[CELL_EDITOR_PORTAL] = new ComponentPortal(this.componentType);
2551
+ class CustomValueColumnModel extends ColumnModel {
2552
+ constructor(columnId, defaults, getValue) {
2553
+ super(columnId, defaults);
2554
+ this.getValue = getValue;
2555
+ this.cellRenderer(DefaultCellRendererComponent);
2624
2556
  }
2625
- onPortalAttached(host, portalComponent) {
2626
- host[PORTAL_EDITOR_COMPONENT] = portalComponent;
2627
- this.initialiseEditorSession(portalComponent, host.editSession);
2557
+ cellRenderer(componentType) {
2558
+ this.configureCellRenderer(new ComponentCellRendererPortalRef(componentType, (component, rowData) => {
2559
+ component.value = this.getValue(rowData.row);
2560
+ }));
2561
+ return this;
2628
2562
  }
2629
2563
  }
2630
- __decorate([
2631
- Trace(),
2632
- __metadata("design:type", Function),
2633
- __metadata("design:paramtypes", [TableCellRendererComponent, Object]),
2634
- __metadata("design:returntype", void 0)
2635
- ], CellEditorPortalRef.prototype, "onPortalAttached", null);
2636
- class TemplateCellRendererPortalRef extends CellRendererPortalRef {
2637
- constructor() {
2638
- super();
2639
- }
2640
- registerPortal(templateRef, viewContainer, fillCell, padChild) {
2641
- this.templateRef = templateRef;
2642
- this.viewContainer = viewContainer;
2643
- this.fillCell = fillCell;
2644
- this.padChild = padChild;
2645
- }
2646
- initialiseHost(host, columnModel) {
2647
- assert$1.isTruthy(host);
2648
- }
2649
- onPortalAttached(host, portalComponent) {
2650
- // don't care
2564
+ class EditorControlColumnModel extends ColumnModel {
2565
+ constructor(columnId, saveCommand, defaults) {
2566
+ super(columnId, defaults);
2567
+ this.cellRenderer(EditRowControls);
2651
2568
  }
2652
- pushState(host) {
2653
- host[CELL_RENDERER_PORTAL] = this.createPortal(host.getRowData());
2654
- host.fillCell = this.fillCell;
2655
- host.padChild = this.padChild;
2569
+ cellRenderer(componentType) {
2570
+ this.configureCellRenderer(new ComponentCellRendererPortalRef(componentType, (component, rowData) => {
2571
+ component.row = rowData.row;
2572
+ component.editSession = rowData.editSession;
2573
+ component.editRowCommand = rowData.editRowCommand;
2574
+ }));
2575
+ return this;
2656
2576
  }
2657
- createPortal(data) {
2658
- return new TemplatePortal(this.templateRef, this.viewContainer, Object.assign(Object.assign({}, (data)), { $implicit: data.row }));
2577
+ getDefaultHeaderText() {
2578
+ return '';
2659
2579
  }
2660
2580
  }
2661
- __decorate([
2662
- Trace(),
2663
- __metadata("design:type", Function),
2664
- __metadata("design:paramtypes", [TableCellRendererComponent, void 0]),
2665
- __metadata("design:returntype", void 0)
2666
- ], TemplateCellRendererPortalRef.prototype, "onPortalAttached", null);
2667
- class ColumnModel {
2581
+ class CustomTemplateColumnModel extends ColumnModel {
2668
2582
  constructor(columnId, defaults) {
2669
- this.columnId = columnId;
2670
- this.defaults = defaults;
2671
- this.cellHeaderRenderer(DefaultHeaderCellRendererComponent, (component, column) => {
2672
- component.headerText = column.getHeaderText();
2673
- });
2674
- }
2675
- getHeaderText() {
2676
- var _a;
2677
- return ((_a = this.getColumnTextProperties()) === null || _a === void 0 ? void 0 : _a.headerText()) || this.getDefaultHeaderText();
2678
- }
2679
- getDefaultHeaderText() {
2680
- return this.columnId;
2681
- }
2682
- getColumnTextProperties() {
2683
- return this._columnTextProperties || this.defaults.getColumnTextProperties(this);
2684
- }
2685
- textProperties(columnTextProperties) {
2686
- this._columnTextProperties = columnTextProperties;
2687
- return this;
2688
- }
2689
- configureHeaderRenderer(config) {
2690
- this._columnHeaderPortalRef = config;
2691
- }
2692
- configureCellRenderer(config) {
2693
- this._cellRendererPortalRef = config;
2694
- }
2695
- configureCellEditor(cellEditor) {
2696
- this._cellEditorPortalRef = cellEditor;
2697
- }
2698
- cellHeaderRenderer(componentType, initialiser) {
2699
- this.configureHeaderRenderer(new CellHeaderPortalRef(componentType, initialiser));
2700
- return this;
2701
- }
2702
- hasEditorPortal() {
2703
- return !!this._cellEditorPortalRef;
2583
+ super(columnId, defaults);
2584
+ this.config = new TemplateCellRendererPortalRef();
2585
+ this.configureCellRenderer(this.config);
2704
2586
  }
2705
- attachHeaderCell(host) {
2706
- this._columnHeaderPortalRef.initialiseHost(host, this);
2587
+ setTemplate(templateRef, viewContainer, fillCell, padChild) {
2588
+ this.config.registerPortal(templateRef, viewContainer, fillCell, padChild);
2707
2589
  }
2708
- attachCell(host) {
2709
- this._cellRendererPortalRef.initialiseHost(host, this);
2710
- if (this.hasEditorPortal()) {
2711
- this._cellEditorPortalRef.initialiseHost(host, this);
2590
+ }
2591
+ class SelectionColumnModel extends ColumnModel {
2592
+ constructor(columnId, defaults, selectionModel) {
2593
+ super(columnId, defaults);
2594
+ if (selectionModel instanceof MultipleSelectionModel) {
2595
+ this.cellHeaderRenderer(SelectHeaderCellRendererComponent, (component) => {
2596
+ component.selectionModel = selectionModel;
2597
+ });
2712
2598
  }
2599
+ this.configureCellRenderer(new ComponentCellRendererPortalRef(SelectCellRendererComponent, (component, rowData) => {
2600
+ component.row = rowData.row;
2601
+ component.selectionModel = selectionModel;
2602
+ }));
2713
2603
  }
2714
- onHeaderAttached(host, component) {
2715
- this._columnHeaderPortalRef.onPortalAttached(host, component);
2716
- }
2717
- onRendererAttached(host, component) {
2718
- this._cellRendererPortalRef.onPortalAttached(host, component);
2719
- }
2720
- onEditorAttached(host, component) {
2721
- this._cellEditorPortalRef.onPortalAttached(host, component);
2722
- }
2723
- updatePortalContent(host) {
2724
- this._cellRendererPortalRef.pushState(host);
2604
+ getDefaultHeaderText() {
2605
+ return '';
2725
2606
  }
2726
2607
  }
2727
- __decorate([
2728
- Memoize(),
2729
- __metadata("design:type", Function),
2730
- __metadata("design:paramtypes", []),
2731
- __metadata("design:returntype", String)
2732
- ], ColumnModel.prototype, "getHeaderText", null);
2733
- __decorate([
2734
- Memoize(),
2735
- __metadata("design:type", Function),
2736
- __metadata("design:paramtypes", []),
2737
- __metadata("design:returntype", Object)
2738
- ], ColumnModel.prototype, "getColumnTextProperties", null);
2739
- __decorate([
2740
- Trace(),
2741
- __metadata("design:type", Function),
2742
- __metadata("design:paramtypes", [TableCellRendererComponent, Object]),
2743
- __metadata("design:returntype", void 0)
2744
- ], ColumnModel.prototype, "onEditorAttached", null);
2745
- class PropertyColumnModel extends ColumnModel {
2746
- constructor(property, defaults) {
2747
- super(property.toString(), defaults);
2748
- this.property = property;
2749
- this._format = (value) => value;
2750
- this.cellRenderer(DefaultCellRendererComponent);
2608
+
2609
+ var TableModel_1;
2610
+ // export type StringPropertiesOf<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T];
2611
+ // export type NumberPropertiesOf<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T];
2612
+ /**
2613
+ * Example:
2614
+ * @example
2615
+ * const model = TableModel.fromList(heroList, table => {
2616
+ * table.pluck("firstName");
2617
+ * table.pluck("lastName");
2618
+ * table.addCustomColumn("fullName", hero => `${hero.firstName} ${hero.lastName}`);
2619
+ * });
2620
+ *
2621
+ * Editable tables
2622
+ * @example
2623
+ * const saveCommand = UnaryCommand.create((form: Form<Hero>) => {
2624
+ * if (form.validate()) {
2625
+ * // normal form save stuff
2626
+ * return true; // finish editing
2627
+ * }
2628
+ * return false; // continue editiing
2629
+ * }
2630
+ * const colorsNames: ListModel<string> = ...;
2631
+ * const model = TableModel.fromList(heroList, table => {
2632
+ * table.pluck("firstName").cellEditor(StringInputComponent); <-- interface CellEditor { valueModel: FormValueModel<string> | ValueModel<string>; }
2633
+ * table.pluck("lastName").cellEditor(StringInputComponent, {
2634
+ * validators: [Validator.present("We need a last name")]
2635
+ * });
2636
+ * table.pluck("age").cellEditor(NumberInputComponent);
2637
+ * table.pluck("favoriteColor").cellEditor(SelectInputComponent, {
2638
+ * initialiseComponent(component: SelectInputComponent) {
2639
+ * selectInput.optionsModel = colorsNames; // <- initialise our component
2640
+ * }
2641
+ * });
2642
+ * table.addEditControls(saveCommand); // <- required to enable editing
2643
+ * });
2644
+ *
2645
+ * Selection models
2646
+ * @example
2647
+ * const model = TableModel.fromList(heroList, table => {
2648
+ * table.addSelectionColumn(selectionModel); // <- can be single or multiple selection model
2649
+ * table.pluck("firstName");
2650
+ * table.pluck("lastName");
2651
+ * });
2652
+ *
2653
+ * Custom cell renderers and editors
2654
+ * @example
2655
+ * const model = TableModel.fromList(heroList, table => {
2656
+ * table.pluck("favoriteColor")
2657
+ * .cellHeaderRenderer(CellHeaderRendererComponent, (component, column) => {
2658
+ * // configure your component with what ever you need.
2659
+ * });
2660
+ * .cellRenderer(CellRendererComponent) // <-- interface CellEditor { value: string; }
2661
+ * .cellEditor(CellEditorComponent.); // <-- interface CellEditor { valueModel: FormValueModel<string> | ValueModel<string>; }
2662
+ * table.addCustomColumn("fullName", hero => `${hero.firstName} ${hero.lastName}`);
2663
+ * });
2664
+ *
2665
+ * I18n
2666
+ * @example
2667
+ * [table.yml]
2668
+ * table:
2669
+ * columns(ColumnTextProperties[]):
2670
+ * firstName:
2671
+ * headerText: "First Name"
2672
+ * fullName:
2673
+ * headerText: "Full Name"
2674
+ *
2675
+ * const model = TableModel.fromList(heroList, table => {
2676
+ * table.pluck("favoriteColor").cellRenderer(...).cellEditor(...);
2677
+ * table.addCustomColumn("fullName", hero => `${hero.firstName} ${hero.lastName}`);
2678
+ *
2679
+ * table.columnTextProperties(I18n.table.columns); // <- configures all columns
2680
+ * });
2681
+ */
2682
+ let TableModel = TableModel_1 = class TableModel {
2683
+ constructor(sourceOfTruth) {
2684
+ this.sourceOfTruth = sourceOfTruth;
2685
+ this._garbage = new GarbageCollector();
2686
+ this._columns = new MutableListModel();
2687
+ this._editorSessions = new MutableListModel();
2688
+ this._createForm = (row) => new Form();
2689
+ this.identityOf = sourceOfTruth.identityOf;
2690
+ const { chain, valueOf, before, when, after, observe, switchOn } = Dsl.disposeWith(this._garbage);
2691
+ this._columnsById = chain(this._columns).indexBy('columnId');
2692
+ this._rowsBeingEdited = new MutableListModel([], {
2693
+ identifiedWith: this.identityOf
2694
+ });
2695
+ this._editorSessionByRowId = chain(this._editorSessions).indexBy('rowId');
2696
+ this.editing = chain(this._editorSessions).count().isGreaterThan(0);
2697
+ this.dataSource = chain(this.sourceOfTruth).replaceAll(this.rowsBeingEdited);
2698
+ this.firstEditableColumn = chain(this.columns).select(c => c.hasEditorPortal()).first();
2751
2699
  }
2752
- cellRenderer(componentType) {
2753
- this.configureCellRenderer(new ComponentCellRendererPortalRef(componentType, (component, rowData) => {
2754
- component.value = this._format(rowData.row[this.property]);
2755
- }));
2756
- return this;
2700
+ static fromList(sourceOfTruth, builder) {
2701
+ const model = new TableModel_1(sourceOfTruth);
2702
+ builder(model);
2703
+ return model;
2757
2704
  }
2758
- cellEditor(editor, validatorsOrInitialiser, initialiseComponent) {
2759
- const validators = Array.isArray(validatorsOrInitialiser) ? validatorsOrInitialiser : undefined;
2760
- const initialiser = ___default.isFunction(validatorsOrInitialiser) ? validatorsOrInitialiser : initialiseComponent;
2761
- this.configureCellEditor(new CellEditorPortalRef(editor, (component, editSession) => {
2762
- const formValueModel = editSession.form.pluck(this.property);
2763
- if (validators) {
2764
- formValueModel.validateUsing(validators);
2765
- }
2766
- component.valueModel = formValueModel;
2767
- if (initialiser) {
2768
- initialiser(component);
2769
- }
2770
- }));
2771
- return this;
2705
+ get rowsBeingEdited() {
2706
+ return this._rowsBeingEdited.readonly;
2772
2707
  }
2773
- format(formatter) {
2774
- assert$1.isFunction(formatter);
2775
- this._format = formatter;
2776
- return this;
2708
+ getTrackByFunction() {
2709
+ return (index, item) => {
2710
+ return this.identityOf ? this.identityOf(item) : index;
2711
+ };
2777
2712
  }
2778
- }
2779
- class ListPropertyColumnModel extends ColumnModel {
2780
- constructor(property, defaults) {
2781
- super(property.toString(), defaults);
2782
- this.property = property;
2783
- this._format = (value) => value.map(v => v === null || v === void 0 ? void 0 : v.toString()).join(', ');
2784
- this.cellRenderer(DefaultCellRendererComponent);
2713
+ get columns() {
2714
+ return this._columns.readonly;
2785
2715
  }
2786
- cellRenderer(componentType) {
2787
- this.configureCellRenderer(new ComponentCellRendererPortalRef(componentType, (component, rowData) => {
2788
- component.value = this._format(rowData.row[this.property]);
2789
- }));
2790
- return this;
2716
+ pluck(property) {
2717
+ return this.addColumn(new PropertyColumnModel(property, this));
2791
2718
  }
2792
- cellEditor(editor, validatorsOrInitialiser, initialiseComponent) {
2793
- const validators = Array.isArray(validatorsOrInitialiser) ? validatorsOrInitialiser : undefined;
2794
- const initialiser = ___default.isFunction(validatorsOrInitialiser) ? validatorsOrInitialiser : initialiseComponent;
2795
- this.configureCellEditor(new CellEditorPortalRef(editor, (component, editSession) => {
2796
- const formListModel = editSession.form.pluckList(this.property);
2797
- if (validators) {
2798
- formListModel.validateUsing(validators);
2799
- }
2800
- component.listModel = formListModel;
2801
- if (initialiser) {
2802
- initialiser(component);
2803
- }
2804
- }));
2805
- return this;
2719
+ pluckList(property) {
2720
+ return this.addColumn(new ListPropertyColumnModel(property, this));
2806
2721
  }
2807
- format(formatter) {
2808
- assert$1.isFunction(formatter);
2809
- this._format = formatter;
2810
- return this;
2722
+ addSelectionColumn(selectionModel) {
2723
+ return this.addColumn(new SelectionColumnModel('selection', this, selectionModel));
2811
2724
  }
2812
- }
2813
- class CustomValueColumnModel extends ColumnModel {
2814
- constructor(columnId, defaults, getValue) {
2815
- super(columnId, defaults);
2816
- this.getValue = getValue;
2817
- this.cellRenderer(DefaultCellRendererComponent);
2725
+ addEditControls(saveCommand) {
2726
+ this.saveCommand = saveCommand;
2727
+ return this.addColumn(new EditorControlColumnModel('editControls', saveCommand, this));
2818
2728
  }
2819
- cellRenderer(componentType) {
2820
- this.configureCellRenderer(new ComponentCellRendererPortalRef(componentType, (component, rowData) => {
2821
- component.value = this.getValue(rowData.row);
2822
- }));
2823
- return this;
2729
+ addCustomColumn(columnId, dataAccessor) {
2730
+ return this.addColumn(new CustomValueColumnModel(columnId, this, dataAccessor));
2824
2731
  }
2825
- }
2826
- class EditorControlColumnModel extends ColumnModel {
2827
- constructor(columnId, saveCommand, defaults) {
2828
- super(columnId, defaults);
2829
- this.cellRenderer(EditRowControls);
2732
+ addTemplateColumn(columnId) {
2733
+ return this.addColumn(new CustomTemplateColumnModel(columnId, this));
2830
2734
  }
2831
- cellRenderer(componentType) {
2832
- this.configureCellRenderer(new ComponentCellRendererPortalRef(componentType, (component, rowData) => {
2833
- component.row = rowData.row;
2834
- component.editSession = rowData.editSession;
2835
- component.editRowCommand = rowData.editRowCommand;
2836
- }));
2735
+ useFormFactory(factory) {
2736
+ this._createForm = factory;
2837
2737
  return this;
2838
2738
  }
2839
- getDefaultHeaderText() {
2840
- return '';
2739
+ addColumn(column) {
2740
+ if (this._columnsById.get(column.columnId)) {
2741
+ lang.illegalState(`Column with id=${column.columnId} already exists`);
2742
+ }
2743
+ else {
2744
+ this._columns.push(column);
2745
+ }
2746
+ return column;
2841
2747
  }
2842
- }
2843
- class CustomTemplateColumnModel extends ColumnModel {
2844
- constructor(columnId, defaults) {
2845
- super(columnId, defaults);
2846
- this.config = new TemplateCellRendererPortalRef();
2847
- this.configureCellRenderer(this.config);
2748
+ columnTextProperties(columnTextProperties) {
2749
+ this._columnTextPropertiesLookup = columnTextProperties;
2848
2750
  }
2849
- setTemplate(templateRef, viewContainer, fillCell, padChild) {
2850
- this.config.registerPortal(templateRef, viewContainer, fillCell, padChild);
2751
+ getColumnTextProperties(column) {
2752
+ const factory = this._columnTextPropertiesLookup ? this._columnTextPropertiesLookup[column.columnId] : undefined;
2753
+ return factory ? factory() : undefined;
2851
2754
  }
2852
- }
2853
- class SelectionColumnModel extends ColumnModel {
2854
- constructor(columnId, defaults, selectionModel) {
2855
- super(columnId, defaults);
2856
- if (selectionModel instanceof MultipleSelectionModel) {
2857
- this.cellHeaderRenderer(SelectHeaderCellRendererComponent, (component) => {
2858
- component.selectionModel = selectionModel;
2755
+ startEditSession(row) {
2756
+ const rowId = this.identityOf(row);
2757
+ if (this._rowsBeingEdited.query().indexOf(row) > -1) {
2758
+ return lang.illegalState(`Row with id=${rowId} already being edited`);
2759
+ }
2760
+ else {
2761
+ const editSession = new EditSession(rowId, row, this._createForm(row), this.saveCommand);
2762
+ const { when } = Dsl.disposeWith(editSession);
2763
+ when.valueOf(editSession.liveRowValue).changes((editedValue) => {
2764
+ this._rowsBeingEdited.replaceOrPush(editedValue);
2765
+ }, { initialValue: 'triggerChangeUnlessNil' });
2766
+ this._editorSessions.push(editSession);
2767
+ editSession.onDispose(() => {
2768
+ this._rowsBeingEdited.remove(editSession.liveRowValue.value);
2769
+ this._editorSessions.remove(editSession);
2859
2770
  });
2771
+ return editSession;
2860
2772
  }
2861
- this.configureCellRenderer(new ComponentCellRendererPortalRef(SelectCellRendererComponent, (component, rowData) => {
2862
- component.row = rowData.row;
2863
- component.selectionModel = selectionModel;
2864
- }));
2865
2773
  }
2866
- getDefaultHeaderText() {
2867
- return '';
2774
+ getEditSessionFor(row) {
2775
+ return this._editorSessionByRowId.get(this.identityOf(row));
2868
2776
  }
2869
- }
2777
+ cancelAllEditorSessions() {
2778
+ this._editorSessions.runInTransaction((draft) => {
2779
+ this._rowsBeingEdited.runInTransaction(() => {
2780
+ draft.value.forEach(session => session.dispose());
2781
+ });
2782
+ });
2783
+ }
2784
+ };
2785
+ TableModel.ctorParameters = () => [
2786
+ { type: ListModel }
2787
+ ];
2788
+ TableModel = TableModel_1 = __decorate([
2789
+ TrackExternal.Strategy(new TrackExternal.OneTimeBinding()),
2790
+ __metadata("design:paramtypes", [ListModel])
2791
+ ], TableModel);
2870
2792
 
2871
2793
  /**
2872
2794
  * Create your model:
@@ -2973,6 +2895,99 @@ ColumnTemplateDirective = __decorate([
2973
2895
  ViewContainerRef])
2974
2896
  ], ColumnTemplateDirective);
2975
2897
 
2898
+ let TableCellRendererComponent = class TableCellRendererComponent extends DisposableComponent {
2899
+ constructor() {
2900
+ super();
2901
+ this.defaultClassNames = 'aup-cell-renderer';
2902
+ this.fillCell = false;
2903
+ this.padChild = false;
2904
+ this.editRowCommand = Command.create(() => {
2905
+ this.tableModel.startEditSession(this.row);
2906
+ });
2907
+ }
2908
+ ngOnInit() {
2909
+ const { chain, valueOf, before, when, after, observe, switchOn } = Dsl.disposeWith(this);
2910
+ this.firstEditableColumn = chain(this.tableModel.firstEditableColumn).equals(this.column); // this would break if the column changed.
2911
+ this.column.attachCell(this);
2912
+ }
2913
+ hasActiveEditor() {
2914
+ return !!this.editSession && !!this.column.hasEditorPortal();
2915
+ }
2916
+ initialiseRenderer(instance) {
2917
+ this.column.onRendererAttached(this, instance);
2918
+ }
2919
+ initialiseEditor(instance) {
2920
+ this.column.onEditorAttached(this, instance);
2921
+ if (this.firstEditableColumn.value) {
2922
+ // @see https://github.com/angular/components/issues/12070
2923
+ setTimeout(() => this.tryAndFocusEditor(instance));
2924
+ }
2925
+ }
2926
+ tryAndFocusEditor(editor) {
2927
+ var _a;
2928
+ if (editor.requestFocus) {
2929
+ editor.requestFocus();
2930
+ }
2931
+ else {
2932
+ const model = (editor['valueModel'] || editor['listModel']);
2933
+ (_a = model === null || model === void 0 ? void 0 : model.focusContext) === null || _a === void 0 ? void 0 : _a.requestFocus();
2934
+ }
2935
+ }
2936
+ // @Trace()
2937
+ ngOnChanges(changes) {
2938
+ this.column.updatePortalContent(this);
2939
+ }
2940
+ getRendererPortal() {
2941
+ return this[CELL_RENDERER_PORTAL];
2942
+ }
2943
+ getEditorPortal() {
2944
+ return this[CELL_EDITOR_PORTAL];
2945
+ }
2946
+ getRowData() {
2947
+ return {
2948
+ row: this.row,
2949
+ editSession: this.editSession,
2950
+ editRowCommand: this.editRowCommand
2951
+ };
2952
+ }
2953
+ };
2954
+ __decorate([
2955
+ Input(),
2956
+ __metadata("design:type", Object)
2957
+ ], TableCellRendererComponent.prototype, "row", void 0);
2958
+ __decorate([
2959
+ Input(),
2960
+ __metadata("design:type", ColumnModel)
2961
+ ], TableCellRendererComponent.prototype, "column", void 0);
2962
+ __decorate([
2963
+ Input(),
2964
+ __metadata("design:type", EditSession)
2965
+ ], TableCellRendererComponent.prototype, "editSession", void 0);
2966
+ __decorate([
2967
+ Input(),
2968
+ __metadata("design:type", TableModel)
2969
+ ], TableCellRendererComponent.prototype, "tableModel", void 0);
2970
+ __decorate([
2971
+ HostBinding('class'),
2972
+ __metadata("design:type", Object)
2973
+ ], TableCellRendererComponent.prototype, "defaultClassNames", void 0);
2974
+ __decorate([
2975
+ HostBinding('class.fillCell'),
2976
+ __metadata("design:type", Object)
2977
+ ], TableCellRendererComponent.prototype, "fillCell", void 0);
2978
+ __decorate([
2979
+ HostBinding('class.padChild'),
2980
+ __metadata("design:type", Object)
2981
+ ], TableCellRendererComponent.prototype, "padChild", void 0);
2982
+ TableCellRendererComponent = __decorate([
2983
+ Component({
2984
+ selector: 'aup-table-cell-renderer',
2985
+ template: "<ng-container *ngIf=\"!hasActiveEditor()\" [cdkPortalOutlet]=\"getRendererPortal()\" (attached)=\"initialiseRenderer($event.instance)\"></ng-container>\n<ng-container *ngIf=\"hasActiveEditor()\" [cdkPortalOutlet]=\"getEditorPortal()\" (attached)=\"initialiseEditor($event.instance)\"></ng-container>\n",
2986
+ styles: [""]
2987
+ }),
2988
+ __metadata("design:paramtypes", [])
2989
+ ], TableCellRendererComponent);
2990
+
2976
2991
  let TableHeaderCellRendererComponent = class TableHeaderCellRendererComponent {
2977
2992
  constructor() {
2978
2993
  this.defaultClassNames = 'aup-header-cell-renderer';
@@ -3186,7 +3201,8 @@ ComponentsModule = __decorate([
3186
3201
  MatCheckboxModule,
3187
3202
  InteractionModule,
3188
3203
  MatTableModule,
3189
- PortalModule
3204
+ PortalModule,
3205
+ CdkScrollableModule
3190
3206
  ],
3191
3207
  exports: [
3192
3208
  NumberInputComponent,
@@ -5041,9 +5057,9 @@ __decorate([
5041
5057
  PlaceOutletComponent = __decorate([
5042
5058
  Component({
5043
5059
  selector: 'aup-place-outlet',
5044
- template: "<ng-container *ngIf=\"animateModel.value\">\n <div class=\"router-outlet-container\"\n [@routeAnimations]=\"{value: getAnimationOrder(), params:{duration: animationDuration}}\"\n (@routeAnimations.start)=\"animationStarted()\"\n (@routeAnimations.done)=\"animationDone()\"\n >\n <router-outlet #routerOutlet=\"outlet\"\n (activate)=\"onOutletActivated(routerOutlet, $event)\"\n (deactivate)=\"onOutletDeactivated()\">\n </router-outlet>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"!animateModel.value\">\n <div class=\"router-outlet-container\">\n <router-outlet #routerOutlet=\"outlet\"\n (activate)=\"onOutletActivated(routerOutlet, $event)\"\n (deactivate)=\"onOutletDeactivated()\">\n </router-outlet>\n </div>\n</ng-container>\n\n",
5060
+ template: "<ng-container *ngIf=\"animateModel.value\">\n <div class=\"router-outlet-container\" cdkScrollable\n [@routeAnimations]=\"{value: getAnimationOrder(), params:{duration: animationDuration}}\"\n (@routeAnimations.start)=\"animationStarted()\"\n (@routeAnimations.done)=\"animationDone()\"\n >\n <router-outlet #routerOutlet=\"outlet\"\n (activate)=\"onOutletActivated(routerOutlet, $event)\"\n (deactivate)=\"onOutletDeactivated()\">\n </router-outlet>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"!animateModel.value\">\n <div class=\"router-outlet-container\" cdkScrollable>\n <router-outlet #routerOutlet=\"outlet\"\n (activate)=\"onOutletActivated(routerOutlet, $event)\"\n (deactivate)=\"onOutletDeactivated()\">\n </router-outlet>\n </div>\n</ng-container>\n\n",
5045
5061
  animations: [LEFT_RIGHT_PLACE_ANIMATION],
5046
- styles: [":host{display:flex;flex-direction:column;min-height:0;overflow-x:hidden}.router-outlet-container{flex:1;display:block;position:relative;min-height:0}router-outlet{display:none}"]
5062
+ styles: [":host{display:flex;flex-direction:column;min-height:0}.router-outlet-container{flex:1;display:block;position:relative;min-height:0;overflow-x:hidden;overflow-y:scroll}router-outlet{display:none}"]
5047
5063
  }),
5048
5064
  __param(2, Optional()), __param(2, Inject(AUP_PLACE_CONFIG)),
5049
5065
  __param(3, SkipSelf()), __param(3, Optional()),