-
Notifications
You must be signed in to change notification settings - Fork 18
/
parent.js
91 lines (76 loc) · 2.58 KB
/
parent.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import Mixin from '@ember/object/mixin';
import { A } from '@ember/array';
import { tryInvoke } from '@ember/utils';
export default Mixin.create({
init() {
this._super(...arguments);
tryInvoke(this, 'initParent');
tryInvoke(this, 'initChild');
},
initParent() {
this.childComponents = A();
},
didInsertElement() {
this._super(...arguments);
// If we are a top-level parent, we should start
// the `didInsertParent` call chain, starting with ourselves
if (!this.get('parentComponent')) {
tryInvoke(this, 'didInsertParent');
this._didInsert = true;
this.invokeChildDidInsertHooks();
}
},
willDestroyElement() {
this._super(...arguments);
if (!this._isComposableDestroying) {
this._isComposableDestroying = true;
tryInvoke(this, 'willDestroyElementParent');
tryInvoke(this, 'willDestroyElementChild');
}
},
willDestroyElementParent() {
this._super(...arguments);
// this wook will be called depth-first from the top-level component
// since we must destroy childs first, the first parent will
// be responsible for destroying the children. `this._didInsert` guards
// that we don't redestroy already destroyed children
if (this._didInsert) {
this.destroySelfAndChildren();
}
},
invokeChildDidInsertHooks() {
this.childComponents.invoke('didInsertParent');
this.childComponents.setEach('_didInsert', true);
this.childComponents.invoke('invokeChildDidInsertHooks');
},
destroySelfAndChildren() {
this.destroyChildren();
tryInvoke(this, 'willDestroyParent');
this._didInsert = false;
},
destroyChildren() {
this.childComponents.reverseObjects();
// if we have child-parents, destroy their children as well
this.childComponents.invoke('destroyChildren');
// destroy children
this.childComponents.invoke('willDestroyParent');
this.childComponents.setEach('_didInsert', false);
this.childComponents.clear();
},
registerChild(childComponent) {
this.childComponents.addObject(childComponent);
// If parent already setup, setup child immediately
if (this._didInsert && !childComponent._didInsert) {
tryInvoke(childComponent, 'didInsertParent');
childComponent._didInsert = true;
tryInvoke(childComponent, 'invokeChildDidInsertHooks');
}
},
unregisterChild(childComponent) {
this.childComponents.removeObject(childComponent);
// If parent already setup, teardown child immediately
if (childComponent._didInsert) {
tryInvoke(childComponent, 'destroySelfAndChildren');
}
}
});