UNPKG

2.7 kBPlain TextView Raw
1import { IStaticResourceConfig } from 'aurelia-templating';
2import { Router } from 'aurelia-router';
3import { DOM } from 'aurelia-pal';
4import * as LogManager from 'aurelia-logging';
5
6const logger = LogManager.getLogger('route-href');
7
8/**
9 * Helper custom attribute to help associate an element with a route by name
10 */
11export class RouteHref {
12
13 /*@internal */
14 static inject() {
15 return [Router, DOM.Element];
16 }
17
18 /**
19 * @internal Actively avoid using decorator to reduce the amount of code generated
20 */
21 static $resource: IStaticResourceConfig = {
22 type: 'attribute',
23 name: 'route-href',
24 bindables: [
25 { name: 'route', changeHandler: 'processChange', primaryProperty: true },
26 { name: 'params', changeHandler: 'processChange' },
27 'attribute'
28 ] as any // type definition of Aurelia templating is wrong
29 };
30
31 /**
32 * Current router of this attribute
33 */
34 readonly router: Router;
35
36 /**
37 * Element this attribute is associated with
38 */
39 readonly element: Element;
40
41 /**@internal */
42 isActive: boolean;
43
44 /**
45 * Name of the route this attribute refers to. This name should exist in the current router hierarchy
46 */
47 route: string;
48
49 /**
50 * Parameters of this attribute to generate URL.
51 */
52 params: Record<string, any>;
53
54 /**
55 * Target property on a custom element if this attribute is put on a custom element
56 * OR an attribute if this attribute is put on a normal element
57 */
58 attribute: string;
59
60 constructor(
61 router: Router,
62 element: Element
63 ) {
64 this.router = router;
65 this.element = element;
66 this.attribute = 'href';
67 }
68
69 bind() {
70 this.isActive = true;
71 this.processChange();
72 }
73
74 unbind() {
75 this.isActive = false;
76 }
77
78 attributeChanged(value: any, previous: any) {
79 if (previous) {
80 this.element.removeAttribute(previous);
81 }
82
83 return this.processChange();
84 }
85
86 processChange() {
87 return this.router
88 .ensureConfigured()
89 .then((): null => {
90 if (!this.isActive) {
91 // returning null to avoid Bluebird warning
92 return null;
93 }
94 const element = this.element as Element & { au: any };
95
96 const href = this.router.generate(this.route, this.params);
97
98 if (element.au.controller) {
99 element.au.controller.viewModel[this.attribute] = href;
100 } else {
101 element.setAttribute(this.attribute, href);
102 }
103
104 // returning null to avoid Bluebird warning
105 return null;
106 })
107 .catch((reason: any) => {
108 logger.error(reason);
109 });
110 }
111}
112