@coolon/angular-ui-powerups 12.0.0-alpha.0 → 12.0.0-alpha.2

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 (33) hide show
  1. package/bundles/coolon-angular-ui-powerups.umd.js +244 -222
  2. package/bundles/coolon-angular-ui-powerups.umd.js.map +1 -1
  3. package/coolon-angular-ui-powerups.metadata.json +1 -1
  4. package/esm2015/lib/place/exports.js +1 -1
  5. package/esm2015/lib/place/exports.js.map +1 -1
  6. package/esm2015/lib/place/exports.metadata.json +1 -1
  7. package/esm2015/lib/place/place-component.js +17 -5
  8. package/esm2015/lib/place/place-component.js.map +1 -1
  9. package/esm2015/lib/place/place-component.metadata.json +1 -1
  10. package/esm2015/lib/place/place-definition.js +1 -1
  11. package/esm2015/lib/place/place-definition.js.map +1 -1
  12. package/esm2015/lib/place/place-definition.metadata.json +1 -1
  13. package/esm2015/lib/place/route/parameter-decorators.js +19 -12
  14. package/esm2015/lib/place/route/parameter-decorators.js.map +1 -1
  15. package/esm2015/lib/place/route/parameter-decorators.metadata.json +1 -1
  16. package/esm2015/lib/place/route/{parameter-definition.class.js → parameter-definition.js} +12 -3
  17. package/esm2015/lib/place/route/parameter-definition.js.map +1 -0
  18. package/esm2015/lib/place/route/{parameter-definition.class.metadata.json → parameter-definition.metadata.json} +1 -1
  19. package/esm2015/lib/place/route/parameter-snapshot.js.map +1 -1
  20. package/esm2015/lib/place/visit.js.map +1 -1
  21. package/fesm2015/coolon-angular-ui-powerups.js +236 -214
  22. package/fesm2015/coolon-angular-ui-powerups.js.map +1 -1
  23. package/lib/place/exports.d.ts +1 -1
  24. package/lib/place/place-component.d.ts +1 -1
  25. package/lib/place/place-definition.d.ts +1 -1
  26. package/lib/place/route/parameter-snapshot.d.ts +1 -1
  27. package/lib/place/visit.d.ts +1 -1
  28. package/package.json +3 -3
  29. package/schematics/activity/templates/component/__name@dasherize__.component.html.template +5 -1
  30. package/schematics/activity/templates/component/__name@dasherize__.component.scss.template +0 -1
  31. package/schematics/activity/templates/component/__name@dasherize__.component.ts.template +7 -0
  32. package/esm2015/lib/place/route/parameter-definition.class.js.map +0 -1
  33. /package/lib/place/route/{parameter-definition.class.d.ts → parameter-definition.d.ts} +0 -0
@@ -5291,6 +5291,204 @@ InteractionModule.decorators = [
5291
5291
  },] }
5292
5292
  ];
5293
5293
 
5294
+ class PlaceHistory {
5295
+ constructor() {
5296
+ this._archive = new Map();
5297
+ this.placeHistoryDepth = 4;
5298
+ }
5299
+ notifyNavigationStarted() {
5300
+ if (this._activeVisits) {
5301
+ this.archive(this._activeVisits.visits);
5302
+ this._previousVisits = this._activeVisits;
5303
+ }
5304
+ }
5305
+ notifyNavigationFinished(visits) {
5306
+ this._activeVisits = new PlaceHistory.VisitRecord(visits);
5307
+ }
5308
+ updateVisit(visit) {
5309
+ assert.isTruthy(this._activeVisits);
5310
+ this._activeVisits.update(visit);
5311
+ }
5312
+ lastVisitIncluded(placeDef) {
5313
+ var _a;
5314
+ return !!((_a = this._previousVisits) === null || _a === void 0 ? void 0 : _a.getVisitFor(placeDef));
5315
+ }
5316
+ getMostRecentVisitFor(placeDef) {
5317
+ return ___default.first(this.getHistory(placeDef));
5318
+ }
5319
+ getHistory(placeDef) {
5320
+ let history = this._archive.get(placeDef);
5321
+ if (!history) {
5322
+ history = [];
5323
+ this.setHistory(placeDef, history);
5324
+ }
5325
+ return history;
5326
+ }
5327
+ setHistory(placeDef, history) {
5328
+ this._archive.set(placeDef, history);
5329
+ }
5330
+ archive(visits) {
5331
+ visits.forEach(state => {
5332
+ const history = this.getHistory(state.placeDefinition);
5333
+ const previousState = ___default.first(history);
5334
+ if (!previousState || state.hasChangedFrom(previousState)) {
5335
+ history.unshift(state); // LIFO
5336
+ this.setHistory(state.placeDefinition, history.slice(0, this.placeHistoryDepth));
5337
+ }
5338
+ });
5339
+ }
5340
+ }
5341
+ PlaceHistory.ɵprov = i0.ɵɵdefineInjectable({ factory: function PlaceHistory_Factory() { return new PlaceHistory(); }, token: PlaceHistory, providedIn: "root" });
5342
+ PlaceHistory.decorators = [
5343
+ { type: Injectable, args: [{
5344
+ providedIn: 'root'
5345
+ },] }
5346
+ ];
5347
+ PlaceHistory.ctorParameters = () => [];
5348
+ (function (PlaceHistory) {
5349
+ class VisitRecord {
5350
+ constructor(visits) {
5351
+ this.visits = visits;
5352
+ }
5353
+ update(visit) {
5354
+ this.visits = this.visits.filter(v => v.placeDefinition !== visit.placeDefinition).concat(visit);
5355
+ }
5356
+ getVisitFor(placeDef) {
5357
+ return this.visits.find(v => v.placeDefinition === placeDef);
5358
+ }
5359
+ }
5360
+ PlaceHistory.VisitRecord = VisitRecord;
5361
+ // export class Query {
5362
+ // private _history: Visit.State[];
5363
+ // private _places: Place[];
5364
+ // private _predicate: (visit: any) => boolean;
5365
+ // private _limit: number;
5366
+ //
5367
+ // constructor(history, limit = history.length) {
5368
+ // this._history = history;
5369
+ // this._places = [];
5370
+ // this._predicate = (visit => true);
5371
+ // this._limit = limit;
5372
+ // }
5373
+ //
5374
+ // to(...places:Place[]):this {
5375
+ // this._places = places;
5376
+ // return this;
5377
+ // }
5378
+ //
5379
+ // with(parameters: { [parameter: string]: any }): this {
5380
+ // this.matching(state => {
5381
+ // return Object.keys(parameters).reduce((acc, key) => {
5382
+ // const matchValue = parameters[key];
5383
+ // const visitValue = state.get(key);
5384
+ // const matched = matchValue === '*' ? !_.isNil(visitValue) : visitValue == matchValue;
5385
+ // // Logger.get(this).info(`matched=${matched}`, parameters, visitValue);
5386
+ // return acc && matched;
5387
+ // }, true);
5388
+ // });
5389
+ // return this;
5390
+ // }
5391
+ //
5392
+ // last(): Visit.State {
5393
+ // return _.findLast(this._history, visit => this._matches(visit))
5394
+ // }
5395
+ //
5396
+ // // @trace
5397
+ // allThatMatch(): Visit.State[] {
5398
+ // return _.filter(this._history, visit => this._matches(visit)).slice(-this._limit);
5399
+ // }
5400
+ //
5401
+ // // @trace
5402
+ // mostRecentValueOf<T=any>(param: string, defaultValue: T = null): T {
5403
+ // const lastStateWithParam = _.findLast(this.allThatMatch(), state => !_.isNil(state.get(param)));
5404
+ // return _.isNil(lastStateWithParam) ? defaultValue : lastStateWithParam.get(param);
5405
+ // }
5406
+ //
5407
+ // limit(limit: number): this {
5408
+ // this._limit = limit;
5409
+ // return this;
5410
+ // }
5411
+ //
5412
+ // matching(predicate: (visit: Visit.State) => boolean): this {
5413
+ // this._predicate = predicate;
5414
+ // return this;
5415
+ // }
5416
+ //
5417
+ // _matches(visit: Visit.State) {
5418
+ // return this._isPlaceMatch(visit) && this._predicate(visit);
5419
+ // }
5420
+ //
5421
+ // _isPlaceMatch(visit: Visit.State) {
5422
+ // return this._places.length < 1 || this._places.includes(visit.place)
5423
+ // }
5424
+ //
5425
+ // }
5426
+ })(PlaceHistory || (PlaceHistory = {}));
5427
+
5428
+ class Visit {
5429
+ constructor(placeDefinition, visitParameters = {}) {
5430
+ this.placeDefinition = placeDefinition;
5431
+ this.visitParameters = visitParameters;
5432
+ }
5433
+ // @Trace()
5434
+ getRouteId() {
5435
+ return this.placeDefinition.getRouteIdFrom(this);
5436
+ }
5437
+ // @Trace()
5438
+ hasRouteId() {
5439
+ return !_.isNil(this.getRouteId());
5440
+ }
5441
+ /**
5442
+ * Returns the value of the place parameter with the specified name. The parameter
5443
+ * name is taken from the `as` option, e.g. {as: 'aCustomName'} otherwise it is the
5444
+ * same as the the ValueModel property name.
5445
+ * @param parameterName the field name of the property model or the `as` option if specified.
5446
+ */
5447
+ getParameter(parameterName) {
5448
+ return this.visitParameters[parameterName];
5449
+ }
5450
+ // @Trace()
5451
+ hasParameter(parameterName) {
5452
+ return Object.keys(this.visitParameters).includes(parameterName);
5453
+ }
5454
+ replace(parameter, value) {
5455
+ return new Visit(this.placeDefinition, Object.assign(Object.assign({}, this.visitParameters), { [parameter.name]: value }));
5456
+ }
5457
+ mergeRouteParameters(routeParams) {
5458
+ // todo: whitelist parameters.
5459
+ const routeParameterKeys = Object.keys(routeParams);
5460
+ const params = {};
5461
+ this.placeDefinition.getVisitParameterDefs().forEach(def => {
5462
+ if (def.isRouteId || def.isRouteParameter) {
5463
+ if (routeParameterKeys.includes(def.name)) {
5464
+ params[def.name] = routeParams[def.name];
5465
+ }
5466
+ }
5467
+ else {
5468
+ // copy non route params as is, but only if they already exist otherwise we'll inject nil values and break the
5469
+ // defaults and remember sanitisation process.
5470
+ const value = this.getParameter(def.name);
5471
+ if (this.hasParameter(def.name)) {
5472
+ params[def.name] = value;
5473
+ }
5474
+ }
5475
+ });
5476
+ return new Visit(this.placeDefinition, params);
5477
+ }
5478
+ hasRoutingChangedFrom(other) {
5479
+ const samePlace = other.placeDefinition === this.placeDefinition;
5480
+ const sameRouteParameters = _.isEqual(this.placeDefinition.getFormattedRouteParameters(this, true), this.placeDefinition.getFormattedRouteParameters(other, true));
5481
+ return !samePlace || !sameRouteParameters;
5482
+ }
5483
+ hasChangedFrom(other) {
5484
+ const sameNonRouteParameters = _.isEqual(this.placeDefinition.getNonRouteParameters(this), this.placeDefinition.getNonRouteParameters(other));
5485
+ return !sameNonRouteParameters || this.hasRoutingChangedFrom(other);
5486
+ }
5487
+ toDebugString() {
5488
+ return Object.keys(this.visitParameters).map(k => `${k}=${this.visitParameters[k]}`).join(',');
5489
+ }
5490
+ }
5491
+
5294
5492
  class ParameterDefinition {
5295
5493
  constructor(propertyName, options, urlFormat) {
5296
5494
  this.propertyName = propertyName;
@@ -5309,7 +5507,6 @@ class ParameterDefinition {
5309
5507
  getOptionValue(key) {
5310
5508
  return this.options.getOptional(key, null);
5311
5509
  }
5312
- // @Trace()
5313
5510
  sanitise(value, visit, placeHistory, injector, isPopState) {
5314
5511
  return __awaiter(this, void 0, void 0, function* () {
5315
5512
  if (this.isMissingFrom(visit)) {
@@ -5330,6 +5527,12 @@ class ParameterDefinition {
5330
5527
  return !visit.hasParameter(this.name);
5331
5528
  }
5332
5529
  }
5530
+ __decorate([
5531
+ Trace(),
5532
+ __metadata("design:type", Function),
5533
+ __metadata("design:paramtypes", [Object, Visit, PlaceHistory, Injector, Boolean]),
5534
+ __metadata("design:returntype", Promise)
5535
+ ], ParameterDefinition.prototype, "sanitise", null);
5333
5536
  (function (ParameterDefinition) {
5334
5537
  class RouteId extends ParameterDefinition {
5335
5538
  constructor() {
@@ -5527,7 +5730,6 @@ class PlaceComponent extends DisposableComponent {
5527
5730
  when(this._active).becomesTruthy(() => this.onPlaceReady());
5528
5731
  this.childPlaces = this.placeDefinition.children.map(d => d.component);
5529
5732
  }
5530
- // @Trace()
5531
5733
  initialiseVisit(visit, notifyVisitChanged) {
5532
5734
  assert.isNil(this.visitModel.value);
5533
5735
  const { when } = Dsl.disposeWith(this);
@@ -5548,18 +5750,17 @@ class PlaceComponent extends DisposableComponent {
5548
5750
  isInitialised() {
5549
5751
  return !!this.visitModel.value;
5550
5752
  }
5551
- // @Trace()
5552
5753
  installBinding(parameterDef) {
5553
5754
  const model = this[parameterDef.propertyName];
5554
5755
  DebugContext.tag(model, `${this.placeDefinition.component.name}.${parameterDef.propertyName}`);
5555
5756
  const binding = this.registerDisposable(new Binding(this.visitModel, model, {
5556
5757
  toRight(visit) {
5557
5758
  const value = visit.getParameter(parameterDef.name);
5558
- // console.log('push to component', { name: parameterDef.name, value, visit });
5759
+ console.log('push to component', { name: parameterDef.name, value, visit });
5559
5760
  return value;
5560
5761
  },
5561
5762
  toLeft(value, currentVisit) {
5562
- // console.log('push to route', { name: parameterDef.name, value, currentVisit });
5763
+ console.log('push to route', { name: parameterDef.name, value, currentVisit });
5563
5764
  return currentVisit.replace(parameterDef, value);
5564
5765
  }
5565
5766
  }));
@@ -5584,6 +5785,18 @@ PlaceComponent.decorators = [
5584
5785
  { type: Directive }
5585
5786
  ];
5586
5787
  PlaceComponent.ctorParameters = () => [];
5788
+ __decorate([
5789
+ Trace(),
5790
+ __metadata("design:type", Function),
5791
+ __metadata("design:paramtypes", [Visit, Function]),
5792
+ __metadata("design:returntype", void 0)
5793
+ ], PlaceComponent.prototype, "initialiseVisit", null);
5794
+ __decorate([
5795
+ Trace(),
5796
+ __metadata("design:type", Function),
5797
+ __metadata("design:paramtypes", [ParameterDefinition]),
5798
+ __metadata("design:returntype", void 0)
5799
+ ], PlaceComponent.prototype, "installBinding", null);
5587
5800
  __decorate([
5588
5801
  Memoize$1(),
5589
5802
  __metadata("design:type", PlaceDefinition),
@@ -6402,140 +6615,6 @@ var PlaceAccessGuard;
6402
6615
  PlaceAccessGuard.NoAuth = NoAuth;
6403
6616
  })(PlaceAccessGuard || (PlaceAccessGuard = {}));
6404
6617
 
6405
- class PlaceHistory {
6406
- constructor() {
6407
- this._archive = new Map();
6408
- this.placeHistoryDepth = 4;
6409
- }
6410
- notifyNavigationStarted() {
6411
- if (this._activeVisits) {
6412
- this.archive(this._activeVisits.visits);
6413
- this._previousVisits = this._activeVisits;
6414
- }
6415
- }
6416
- notifyNavigationFinished(visits) {
6417
- this._activeVisits = new PlaceHistory.VisitRecord(visits);
6418
- }
6419
- updateVisit(visit) {
6420
- assert.isTruthy(this._activeVisits);
6421
- this._activeVisits.update(visit);
6422
- }
6423
- lastVisitIncluded(placeDef) {
6424
- var _a;
6425
- return !!((_a = this._previousVisits) === null || _a === void 0 ? void 0 : _a.getVisitFor(placeDef));
6426
- }
6427
- getMostRecentVisitFor(placeDef) {
6428
- return ___default.first(this.getHistory(placeDef));
6429
- }
6430
- getHistory(placeDef) {
6431
- let history = this._archive.get(placeDef);
6432
- if (!history) {
6433
- history = [];
6434
- this.setHistory(placeDef, history);
6435
- }
6436
- return history;
6437
- }
6438
- setHistory(placeDef, history) {
6439
- this._archive.set(placeDef, history);
6440
- }
6441
- archive(visits) {
6442
- visits.forEach(state => {
6443
- const history = this.getHistory(state.placeDefinition);
6444
- const previousState = ___default.first(history);
6445
- if (!previousState || state.hasChangedFrom(previousState)) {
6446
- history.unshift(state); // LIFO
6447
- this.setHistory(state.placeDefinition, history.slice(0, this.placeHistoryDepth));
6448
- }
6449
- });
6450
- }
6451
- }
6452
- PlaceHistory.ɵprov = i0.ɵɵdefineInjectable({ factory: function PlaceHistory_Factory() { return new PlaceHistory(); }, token: PlaceHistory, providedIn: "root" });
6453
- PlaceHistory.decorators = [
6454
- { type: Injectable, args: [{
6455
- providedIn: 'root'
6456
- },] }
6457
- ];
6458
- PlaceHistory.ctorParameters = () => [];
6459
- (function (PlaceHistory) {
6460
- class VisitRecord {
6461
- constructor(visits) {
6462
- this.visits = visits;
6463
- }
6464
- update(visit) {
6465
- this.visits = this.visits.filter(v => v.placeDefinition !== visit.placeDefinition).concat(visit);
6466
- }
6467
- getVisitFor(placeDef) {
6468
- return this.visits.find(v => v.placeDefinition === placeDef);
6469
- }
6470
- }
6471
- PlaceHistory.VisitRecord = VisitRecord;
6472
- // export class Query {
6473
- // private _history: Visit.State[];
6474
- // private _places: Place[];
6475
- // private _predicate: (visit: any) => boolean;
6476
- // private _limit: number;
6477
- //
6478
- // constructor(history, limit = history.length) {
6479
- // this._history = history;
6480
- // this._places = [];
6481
- // this._predicate = (visit => true);
6482
- // this._limit = limit;
6483
- // }
6484
- //
6485
- // to(...places:Place[]):this {
6486
- // this._places = places;
6487
- // return this;
6488
- // }
6489
- //
6490
- // with(parameters: { [parameter: string]: any }): this {
6491
- // this.matching(state => {
6492
- // return Object.keys(parameters).reduce((acc, key) => {
6493
- // const matchValue = parameters[key];
6494
- // const visitValue = state.get(key);
6495
- // const matched = matchValue === '*' ? !_.isNil(visitValue) : visitValue == matchValue;
6496
- // // Logger.get(this).info(`matched=${matched}`, parameters, visitValue);
6497
- // return acc && matched;
6498
- // }, true);
6499
- // });
6500
- // return this;
6501
- // }
6502
- //
6503
- // last(): Visit.State {
6504
- // return _.findLast(this._history, visit => this._matches(visit))
6505
- // }
6506
- //
6507
- // // @trace
6508
- // allThatMatch(): Visit.State[] {
6509
- // return _.filter(this._history, visit => this._matches(visit)).slice(-this._limit);
6510
- // }
6511
- //
6512
- // // @trace
6513
- // mostRecentValueOf<T=any>(param: string, defaultValue: T = null): T {
6514
- // const lastStateWithParam = _.findLast(this.allThatMatch(), state => !_.isNil(state.get(param)));
6515
- // return _.isNil(lastStateWithParam) ? defaultValue : lastStateWithParam.get(param);
6516
- // }
6517
- //
6518
- // limit(limit: number): this {
6519
- // this._limit = limit;
6520
- // return this;
6521
- // }
6522
- //
6523
- // matching(predicate: (visit: Visit.State) => boolean): this {
6524
- // this._predicate = predicate;
6525
- // return this;
6526
- // }
6527
- //
6528
- // _matches(visit: Visit.State) {
6529
- // return this._isPlaceMatch(visit) && this._predicate(visit);
6530
- // }
6531
- //
6532
- // _isPlaceMatch(visit: Visit.State) {
6533
- // return this._places.length < 1 || this._places.includes(visit.place)
6534
- // }
6535
- //
6536
- // }
6537
- })(PlaceHistory || (PlaceHistory = {}));
6538
-
6539
6618
  class UrlSnapshot {
6540
6619
  // TODO: Update this accept a url Parser so it can be immutable and generate new trees on mutation using toString() are parseUrl.
6541
6620
  constructor(urlSerializer, url) {
@@ -7008,70 +7087,6 @@ PlaceRouter.ctorParameters = () => [
7008
7087
  PlaceRouter.State = State;
7009
7088
  })(PlaceRouter || (PlaceRouter = {}));
7010
7089
 
7011
- class Visit {
7012
- constructor(placeDefinition, visitParameters = {}) {
7013
- this.placeDefinition = placeDefinition;
7014
- this.visitParameters = visitParameters;
7015
- }
7016
- // @Trace()
7017
- getRouteId() {
7018
- return this.placeDefinition.getRouteIdFrom(this);
7019
- }
7020
- // @Trace()
7021
- hasRouteId() {
7022
- return !_.isNil(this.getRouteId());
7023
- }
7024
- /**
7025
- * Returns the value of the place parameter with the specified name. The parameter
7026
- * name is taken from the `as` option, e.g. {as: 'aCustomName'} otherwise it is the
7027
- * same as the the ValueModel property name.
7028
- * @param parameterName the field name of the property model or the `as` option if specified.
7029
- */
7030
- getParameter(parameterName) {
7031
- return this.visitParameters[parameterName];
7032
- }
7033
- // @Trace()
7034
- hasParameter(parameterName) {
7035
- return Object.keys(this.visitParameters).includes(parameterName);
7036
- }
7037
- replace(parameter, value) {
7038
- return new Visit(this.placeDefinition, Object.assign(Object.assign({}, this.visitParameters), { [parameter.name]: value }));
7039
- }
7040
- mergeRouteParameters(routeParams) {
7041
- // todo: whitelist parameters.
7042
- const routeParameterKeys = Object.keys(routeParams);
7043
- const params = {};
7044
- this.placeDefinition.getVisitParameterDefs().forEach(def => {
7045
- if (def.isRouteId || def.isRouteParameter) {
7046
- if (routeParameterKeys.includes(def.name)) {
7047
- params[def.name] = routeParams[def.name];
7048
- }
7049
- }
7050
- else {
7051
- // copy non route params as is, but only if they already exist otherwise we'll inject nil values and break the
7052
- // defaults and remember sanitisation process.
7053
- const value = this.getParameter(def.name);
7054
- if (this.hasParameter(def.name)) {
7055
- params[def.name] = value;
7056
- }
7057
- }
7058
- });
7059
- return new Visit(this.placeDefinition, params);
7060
- }
7061
- hasRoutingChangedFrom(other) {
7062
- const samePlace = other.placeDefinition === this.placeDefinition;
7063
- const sameRouteParameters = _.isEqual(this.placeDefinition.getFormattedRouteParameters(this, true), this.placeDefinition.getFormattedRouteParameters(other, true));
7064
- return !samePlace || !sameRouteParameters;
7065
- }
7066
- hasChangedFrom(other) {
7067
- const sameNonRouteParameters = _.isEqual(this.placeDefinition.getNonRouteParameters(this), this.placeDefinition.getNonRouteParameters(other));
7068
- return !sameNonRouteParameters || this.hasRoutingChangedFrom(other);
7069
- }
7070
- toDebugString() {
7071
- return Object.keys(this.visitParameters).map(k => `${k}=${this.visitParameters[k]}`).join(',');
7072
- }
7073
- }
7074
-
7075
7090
  const AUP_PLACE_CONFIG = new InjectionToken('AUP_PLACE_CONFIG');
7076
7091
 
7077
7092
  class NotAuthorisedNoticeComponent {
@@ -7996,18 +8011,25 @@ var Formatter;
7996
8011
  Formatter.BOOLEAN = new BooleanType();
7997
8012
  })(Formatter || (Formatter = {}));
7998
8013
 
7999
- function installMechanics(prototype, propertyKey, backingModel, tagPrefix, isEmpty) {
8000
- const mechanics = {
8001
- backingModel: backingModel,
8002
- binding: null
8003
- };
8004
- const tag = `${tagPrefix}(${prototype.constructor.name}.${propertyKey.toString()})`;
8005
- DebugContext.getOrCreate(mechanics.backingModel).tag(tag);
8014
+ function installMechanics(prototype, propertyKey, backingModelFactory, tagPrefix, isEmpty) {
8015
+ function getMechanics(instance, propertyName) {
8016
+ const key = `__mechanics_${propertyName.toString()}`;
8017
+ if (!instance[key]) {
8018
+ instance[key] = {
8019
+ backingModel: backingModelFactory(),
8020
+ binding: null
8021
+ };
8022
+ const tag = `${tagPrefix}(${prototype.constructor.name}.${propertyKey.toString()})`;
8023
+ DebugContext.getOrCreate(instance[key].backingModel).tag(tag);
8024
+ }
8025
+ return instance[key];
8026
+ }
8006
8027
  Object.defineProperty(prototype, propertyKey, {
8007
8028
  get: function () {
8008
- return mechanics.backingModel;
8029
+ return getMechanics(this, propertyKey).backingModel;
8009
8030
  },
8010
8031
  set: function (userModel) {
8032
+ const mechanics = getMechanics(this, propertyKey);
8011
8033
  // This handles the scenario where we want to push an existing value model (such as a form model)
8012
8034
  // to and from the route.
8013
8035
  if (mechanics.binding) {
@@ -8036,7 +8058,7 @@ function RouteId(type, options) {
8036
8058
  return (prototype, propertyKey) => {
8037
8059
  const param = new ParameterDefinition.RouteId(propertyKey.toString(), options, type);
8038
8060
  Klass.get(prototype).addToOwnMetadataList(ROUTE_PARAMETER_LIST_KEY, param);
8039
- installMechanics(prototype, propertyKey, new MutableValueModel(), '@RouteId', m => m.query().isNil());
8061
+ installMechanics(prototype, propertyKey, () => new MutableValueModel(), '@RouteId', m => m.query().isNil());
8040
8062
  };
8041
8063
  }
8042
8064
  function VisitParameter(options) {
@@ -8044,7 +8066,7 @@ function VisitParameter(options) {
8044
8066
  return (prototype, propertyKey) => {
8045
8067
  const param = new ParameterDefinition.ValueParameter(propertyKey.toString(), options, opts.getOptional('storeInUrl', null));
8046
8068
  Klass.get(prototype).addToOwnMetadataList(ROUTE_PARAMETER_LIST_KEY, param);
8047
- installMechanics(prototype, propertyKey, new MutableValueModel(), '@VisitParameter', m => m.query().isNil());
8069
+ installMechanics(prototype, propertyKey, () => new MutableValueModel(), '@VisitParameter', m => m.query().isNil());
8048
8070
  };
8049
8071
  }
8050
8072
  function VisitParameterList(options) {
@@ -8052,7 +8074,7 @@ function VisitParameterList(options) {
8052
8074
  return (prototype, propertyKey) => {
8053
8075
  const param = new ParameterDefinition.ArrayParameter(propertyKey.toString(), options, opts.getOptional('storeInUrl', null));
8054
8076
  Klass.get(prototype).addToOwnMetadataList(ROUTE_PARAMETER_LIST_KEY, param);
8055
- installMechanics(prototype, propertyKey, new MutableListModel(), '@VisitParameterList', m => m.query().isEmpty());
8077
+ installMechanics(prototype, propertyKey, () => new MutableListModel(), '@VisitParameterList', m => m.query().isEmpty());
8056
8078
  };
8057
8079
  }
8058
8080