@@ -8,44 +8,46 @@ import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nod
8
8
/**
9
9
* A controller for providing content to slot element and observing changes.
10
10
*/
11
- export class SlotController {
11
+ export class SlotController extends EventTarget {
12
12
constructor ( host , slotName , slotFactory , slotInitializer ) {
13
+ super ( ) ;
14
+
13
15
this . host = host ;
14
16
this . slotName = slotName ;
15
17
this . slotFactory = slotFactory ;
16
18
this . slotInitializer = slotInitializer ;
19
+ this . defaultId = SlotController . generateId ( slotName , host ) ;
20
+ }
21
+
22
+ /**
23
+ * Ensure that every instance has unique ID.
24
+ *
25
+ * @param {string } slotName
26
+ * @param {HTMLElement } host
27
+ * @return {string }
28
+ * @protected
29
+ */
30
+ static generateId ( slotName , host ) {
31
+ const prefix = slotName || 'default' ;
32
+
33
+ // Maintain the unique ID counter for a given prefix.
34
+ this [ `${ prefix } Id` ] = 1 + this [ `${ prefix } Id` ] || 0 ;
35
+
36
+ return `${ prefix } -${ host . localName } -${ this [ `${ prefix } Id` ] } ` ;
17
37
}
18
38
19
39
hostConnected ( ) {
20
40
if ( ! this . initialized ) {
21
- const { host, slotName, slotFactory, slotInitializer } = this ;
22
-
23
- const slotted = this . getSlotChild ( ) ;
24
-
25
- if ( ! slotted ) {
26
- // Slot factory is optional, some slots don't have default content.
27
- if ( slotFactory ) {
28
- const slotContent = slotFactory ( host ) ;
29
- if ( slotContent instanceof Element ) {
30
- if ( slotName !== '' ) {
31
- slotContent . setAttribute ( 'slot' , slotName ) ;
32
- }
33
- host . appendChild ( slotContent ) ;
34
- this . node = slotContent ;
35
-
36
- // Store reference to not pass default node to `initCustomNode`.
37
- this . defaultNode = slotContent ;
38
- }
39
- }
41
+ let node = this . getSlotChild ( ) ;
42
+
43
+ if ( ! node ) {
44
+ node = this . attachDefaultNode ( ) ;
40
45
} else {
41
- this . node = slotted ;
46
+ this . node = node ;
47
+ this . initCustomNode ( node ) ;
42
48
}
43
49
44
- // Don't try to bind `this` to initializer (normally it's arrow function).
45
- // Instead, pass the host as a first argument to access component's state.
46
- if ( slotInitializer ) {
47
- slotInitializer ( host , this . node ) ;
48
- }
50
+ this . initNode ( node ) ;
49
51
50
52
// TODO: Consider making this behavior opt-in to improve performance.
51
53
this . observe ( ) ;
@@ -54,6 +56,36 @@ export class SlotController {
54
56
}
55
57
}
56
58
59
+ /**
60
+ * Create and attach default node using the slot factory.
61
+ * @return {Node | undefined }
62
+ * @protected
63
+ */
64
+ attachDefaultNode ( ) {
65
+ const { host, slotName, slotFactory } = this ;
66
+
67
+ // Check if the node was created previously and if so, reuse it.
68
+ let node = this . defaultNode ;
69
+
70
+ // Slot factory is optional, some slots don't have default content.
71
+ if ( ! node && slotFactory ) {
72
+ node = slotFactory ( host ) ;
73
+ if ( node instanceof Element ) {
74
+ if ( slotName !== '' ) {
75
+ node . setAttribute ( 'slot' , slotName ) ;
76
+ }
77
+ this . node = node ;
78
+ this . defaultNode = node ;
79
+ }
80
+ }
81
+
82
+ if ( node ) {
83
+ host . appendChild ( node ) ;
84
+ }
85
+
86
+ return node ;
87
+ }
88
+
57
89
/**
58
90
* Return a reference to the node managed by the controller.
59
91
* @return {Node }
@@ -69,6 +101,19 @@ export class SlotController {
69
101
} ) ;
70
102
}
71
103
104
+ /**
105
+ * @param {Node } node
106
+ * @protected
107
+ */
108
+ initNode ( node ) {
109
+ const { slotInitializer } = this ;
110
+ // Don't try to bind `this` to initializer (normally it's arrow function).
111
+ // Instead, pass the host as a first argument to access component's state.
112
+ if ( slotInitializer ) {
113
+ slotInitializer ( this . host , node ) ;
114
+ }
115
+ }
116
+
72
117
/**
73
118
* Override to initialize the newly added custom node.
74
119
*
@@ -115,6 +160,8 @@ export class SlotController {
115
160
116
161
if ( newNode !== this . defaultNode ) {
117
162
this . initCustomNode ( newNode ) ;
163
+
164
+ this . initNode ( newNode ) ;
118
165
}
119
166
}
120
167
} ) ;
0 commit comments