UNPKG

3.03 kBPlain TextView Raw
1import { ViewFactory, ViewSlot } from 'aurelia-templating';
2
3/**
4 * For internal use only. May change without warning.
5 */
6export class IfCore {
7 /**
8 * @internal
9 */
10 viewFactory: ViewFactory;
11 /**
12 * @internal
13 */
14 viewSlot: ViewSlot;
15 /**
16 * @internal
17 */
18 view: any;
19 /**
20 * @internal
21 */
22 bindingContext: any;
23 /**
24 * @internal
25 */
26 overrideContext: any;
27 /**
28 * @internal
29 */
30 showing: boolean;
31 /**
32 * @internal
33 */
34 cache: boolean | string;
35
36 constructor(viewFactory: ViewFactory, viewSlot: ViewSlot) {
37 this.viewFactory = viewFactory;
38 this.viewSlot = viewSlot;
39 this.view = null;
40 this.bindingContext = null;
41 this.overrideContext = null;
42 // If the child view is animated, `value` might not reflect the internal
43 // state anymore, so we use `showing` for that.
44 // Eventually, `showing` and `value` should be consistent.
45 this.showing = false;
46 this.cache = true;
47 }
48
49 bind(bindingContext, overrideContext) {
50 // Store parent bindingContext, so we can pass it down
51 this.bindingContext = bindingContext;
52 this.overrideContext = overrideContext;
53 }
54
55 unbind() {
56 if (this.view === null) {
57 return;
58 }
59
60 this.view.unbind();
61
62 // It seems to me that this code is subject to race conditions when animating.
63 // For example a view could be returned to the cache and reused while it's still
64 // attached to the DOM and animated.
65 if (!this.viewFactory.isCaching) {
66 return;
67 }
68
69 if (this.showing) {
70 this.showing = false;
71 this.viewSlot.remove(this.view, /*returnToCache:*/true, /*skipAnimation:*/true);
72 } else {
73 this.view.returnToCache();
74 }
75
76 this.view = null;
77 }
78
79 /**
80 * @internal
81 */
82 _show() {
83 if (this.showing) {
84 // Ensures the view is bound.
85 // It might not be the case when the if was unbound but not detached, then rebound.
86 // Typical case where this happens is nested ifs
87 if (!this.view.isBound) {
88 this.view.bind(this.bindingContext, this.overrideContext);
89 }
90 return;
91 }
92
93 if (this.view === null) {
94 this.view = (this.viewFactory as any).create();
95 }
96
97 if (!this.view.isBound) {
98 this.view.bind(this.bindingContext, this.overrideContext);
99 }
100
101 this.showing = true;
102 return this.viewSlot.add(this.view); // Promise or void
103 }
104
105 /**
106 * @internal
107 */
108 _hide() {
109 if (!this.showing) {
110 return;
111 }
112
113 this.showing = false;
114 let removed = this.viewSlot.remove(this.view); // Promise or View
115
116 if (removed instanceof Promise) {
117 return removed.then(() => {
118 this._unbindView();
119 });
120 }
121
122 this._unbindView();
123 }
124
125 /**
126 * @internal
127 */
128 _unbindView() {
129 const cache = this.cache === 'false' ? false : !!this.cache;
130 this.view.unbind();
131 if (!cache) {
132 this.view = null;
133 }
134 }
135}