@webtides/element-js 1.0.0-alpha.9 → 1.1.0
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.
- package/CHANGELOG.md +369 -0
- package/README.md +3 -3
- package/docs/README.md +70 -89
- package/docs/concepts/classes.md +37 -66
- package/docs/concepts/hierarchy.md +29 -31
- package/docs/concepts/lifecycle.md +9 -23
- package/docs/concepts/reactivity.md +1 -3
- package/docs/features/computed-properties.md +13 -16
- package/docs/features/dependency-injection-context-protocol.md +75 -87
- package/docs/features/global-styles.md +1 -1
- package/docs/features/methods.md +14 -15
- package/docs/features/properties.md +21 -33
- package/docs/features/refs.md +23 -31
- package/docs/features/renderless.md +31 -37
- package/docs/features/store.md +63 -78
- package/docs/features/templates.md +4 -1
- package/docs/features/watch.md +28 -35
- package/docs/getting-started/upgrade-to-v1.md +16 -0
- package/docs/guide/guide.md +10 -22
- package/index.js +29 -2
- package/package.json +62 -62
- package/src/BaseElement.js +637 -632
- package/src/StyledElement.js +104 -104
- package/src/TemplateElement.js +53 -58
- package/src/dom-parts/AttributePart.js +116 -116
- package/src/dom-parts/ChildNodePart.js +288 -288
- package/src/dom-parts/NodePart.js +27 -27
- package/src/dom-parts/Part.js +6 -6
- package/src/dom-parts/TemplatePart.js +119 -119
- package/src/dom-parts/TemplateResult.js +274 -267
- package/src/dom-parts/directives.js +105 -48
- package/src/dom-parts/html.js +2 -2
- package/src/dom-parts/render.js +6 -1
- package/src/util/AttributeParser.js +47 -47
- package/src/util/DOMHelper.js +190 -191
- package/src/util/Directive.js +31 -24
- package/src/util/GlobalStylesStore.js +56 -49
- package/src/util/SerializeStateHelper.js +56 -56
- package/src/util/Store.js +174 -174
- package/src/util/defineElement.js +5 -5
- package/src/util/toString.js +5 -5
package/docs/concepts/classes.md
CHANGED
|
@@ -4,8 +4,7 @@ Most of the _element-js_ API ist standard ES6 class Syntax with a few ES next pr
|
|
|
4
4
|
|
|
5
5
|
An _element-js_ element is nothing more than a regular JS class that extends from `HTMLElement`.
|
|
6
6
|
|
|
7
|
-
> For more information on JavaScript classes
|
|
8
|
-
> see: [Classes on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
|
|
7
|
+
> For more information on JavaScript classes see: [Classes on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
|
|
9
8
|
|
|
10
9
|
### Constructor & Options
|
|
11
10
|
|
|
@@ -15,42 +14,36 @@ Optionally you can overwrite the constructor and pass an object to the super cal
|
|
|
15
14
|
|
|
16
15
|
```json
|
|
17
16
|
{
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
"autoUpdate": true,
|
|
18
|
+
"deferUpdate": false,
|
|
19
|
+
"mutationObserverOptions": {
|
|
20
|
+
"attributes": true,
|
|
21
|
+
"childList": true,
|
|
22
|
+
"subtree": false
|
|
23
|
+
},
|
|
24
|
+
"propertyOptions": {},
|
|
25
|
+
"shadowRender": false,
|
|
26
|
+
"styles": []
|
|
28
27
|
}
|
|
29
28
|
```
|
|
30
29
|
|
|
31
|
-
|
|
32
30
|
#### autoUpdate
|
|
33
31
|
|
|
34
32
|
Type: `boolean` Default: `true`
|
|
35
33
|
|
|
36
|
-
When set to `true` the element will call the `requestUpdate()` method on the instance every time a property or attribute
|
|
37
|
-
was changed. This will re-evaluate everything on the element and trigger a re-render (if a template is provided) and
|
|
38
|
-
trigger the watchers for the affected properties/attributes.
|
|
34
|
+
When set to `true` the element will call the `requestUpdate()` method on the instance every time a property or attribute was changed. This will re-evaluate everything on the element and trigger a re-render (if a template is provided) and trigger the watchers for the affected properties/attributes.
|
|
39
35
|
|
|
40
36
|
#### deferUpdate
|
|
41
37
|
|
|
42
38
|
Type: `boolean` Default: `false`
|
|
43
39
|
|
|
44
|
-
When set to `true` the element will not call the `requestUpdate()` method upon connecting and therefore will not
|
|
45
|
-
render (if template was provided) initially. This might be necessary in some cases where you have to prepare and setup
|
|
46
|
-
your element before actually rendering for the first time. You will have to call the `requestUpdate` method manually at
|
|
47
|
-
the right lifecycle hook.
|
|
40
|
+
When set to `true` the element will not call the `requestUpdate()` method upon connecting and therefore will not render (if template was provided) initially. This might be necessary in some cases where you have to prepare and setup your element before actually rendering for the first time. You will have to call the `requestUpdate` method manually at the right lifecycle hook.
|
|
48
41
|
|
|
49
42
|
#### deferUpdate via attribute
|
|
50
43
|
|
|
51
44
|
deferUpdate can also be set to true by adding a "defer-update" attribute to the host element.
|
|
52
45
|
|
|
53
|
-
```html
|
|
46
|
+
```html
|
|
54
47
|
<deferred-element defer-update></deferred-element>
|
|
55
48
|
```
|
|
56
49
|
|
|
@@ -58,34 +51,23 @@ deferUpdate can also be set to true by adding a "defer-update" attribute to the
|
|
|
58
51
|
|
|
59
52
|
Type: `boolean` Default: `false`
|
|
60
53
|
|
|
61
|
-
When set to `true` the element will early return from the native `connectedCallback()`.
|
|
62
|
-
Setting this to true will defer the entire initialization of `element-js` feature set.
|
|
63
|
-
To make the element useful at a later point again `connectedCallback()` must be called at a later point.
|
|
54
|
+
When set to `true` the element will early return from the native `connectedCallback()`. Setting this to true will defer the entire initialization of `element-js` feature set. To make the element useful at a later point again `connectedCallback()` must be called at a later point.
|
|
64
55
|
|
|
65
56
|
This is an advanced Setting and should be used with great caution.
|
|
66
57
|
|
|
67
|
-
|
|
68
58
|
#### deferConnected via attribute (⚠️)
|
|
69
59
|
|
|
70
60
|
deferConnected can also be set to true by adding a "defer-connected" attribute to the host element.
|
|
71
61
|
|
|
72
|
-
```html
|
|
62
|
+
```html
|
|
73
63
|
<deferred-element defer-connected></deferred-element>
|
|
74
64
|
```
|
|
75
65
|
|
|
76
|
-
|
|
77
|
-
|
|
78
66
|
#### mutationObserverOptions
|
|
79
67
|
|
|
80
68
|
Type: `object` Default: `{ "attributes": true, "childList": true, "subtree": false }`
|
|
81
69
|
|
|
82
|
-
By default, the element will register a _Mutation Observer_, listen for attribute changes and call the `requestUpdate`
|
|
83
|
-
method if `autoUpdate` is enabled. When `childList` is set to `true` the element will also call the `requestUpdate`
|
|
84
|
-
method for childList modifications (eg. Adding or removing child elements).
|
|
85
|
-
The `mutationObserverOptions` takes a dictionary in the exact same form as
|
|
86
|
-
the [MutationObserverInit options](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit).
|
|
87
|
-
By setting the `subtree` option to `true` the element will also call the `requestUpdate` method for attribute changes
|
|
88
|
-
and childList modifications on nested child elements.
|
|
70
|
+
By default, the element will register a _Mutation Observer_, listen for attribute changes and call the `requestUpdate` method if `autoUpdate` is enabled. When `childList` is set to `true` the element will also call the `requestUpdate` method for childList modifications (eg. Adding or removing child elements). The `mutationObserverOptions` takes a dictionary in the exact same form as the [MutationObserverInit options](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit). By setting the `subtree` option to `true` the element will also call the `requestUpdate` method for attribute changes and childList modifications on nested child elements.
|
|
89
71
|
|
|
90
72
|
> Please note that observing `subtree` mutations might have performance implications and use it only if necessary.
|
|
91
73
|
|
|
@@ -108,9 +90,9 @@ With the `propertyOptions` object you can fine tune the update behaviour for cer
|
|
|
108
90
|
|
|
109
91
|
```json
|
|
110
92
|
{
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
93
|
+
"propertyA": {
|
|
94
|
+
"reflect": true
|
|
95
|
+
}
|
|
114
96
|
}
|
|
115
97
|
```
|
|
116
98
|
|
|
@@ -118,50 +100,39 @@ By default all options are `false` for all properties/attributes. Currently the
|
|
|
118
100
|
|
|
119
101
|
```json
|
|
120
102
|
{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
103
|
+
"reflect": false,
|
|
104
|
+
"parse": false,
|
|
105
|
+
"notify": false
|
|
124
106
|
}
|
|
125
107
|
```
|
|
126
108
|
|
|
127
|
-
_reflect_ When set to `true` the element will reflect property changes back to attributes if the attribute was not
|
|
128
|
-
present when connecting the element. By default all attributes that are present when connecting the element will be
|
|
129
|
-
reflected anyway.
|
|
130
|
-
|
|
131
|
-
_parse_ When set to `false` the element will not automatically try to parse the attributes string value to a complex
|
|
132
|
-
type (number, array, object).
|
|
109
|
+
_reflect_ When set to `true` the element will reflect property changes back to attributes if the attribute was not present when connecting the element. By default all attributes that are present when connecting the element will be reflected anyway.
|
|
133
110
|
|
|
134
|
-
|
|
135
|
-
will be the property name all lowercase and camel to dashes with a postfix of `-changed`. For example `propertyA` will
|
|
136
|
-
dispatch an event with the name `property-a-changed` . The event `detail` property will be the changed property value.
|
|
137
|
-
The event will `bubble` by default.
|
|
111
|
+
_parse_ When set to `false` the element will not automatically try to parse the attributes string value to a complex type (number, array, object).
|
|
138
112
|
|
|
139
|
-
|
|
140
|
-
of the attributes value
|
|
113
|
+
_notify_ When set to `true` the element will dispatch `CustomEvent`s for every property/attribute change. The event name will be the property name all lowercase and camel to dashes with a postfix of `-changed`. For example `propertyA` will dispatch an event with the name `property-a-changed` . The event `detail` property will be the changed property value. The event will `bubble` by default.
|
|
141
114
|
|
|
142
|
-
|
|
115
|
+
_parse_ and _reflect_ can also be provided with a callback function for total control of the parsing and/or reflection of the attributes value
|
|
143
116
|
|
|
117
|
+
```js
|
|
144
118
|
propertyOptions = {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
119
|
+
parseString: {
|
|
120
|
+
parse: (value) => value.toString()
|
|
121
|
+
},
|
|
122
|
+
reflectCustom: {
|
|
123
|
+
reflect: () => 'custom'
|
|
124
|
+
}
|
|
125
|
+
};
|
|
152
126
|
```
|
|
153
127
|
|
|
154
128
|
#### shadowRender
|
|
155
129
|
|
|
156
130
|
Type: `boolean` Default: `false`
|
|
157
131
|
|
|
158
|
-
When set to `true` the element will render the template (if provided) in the _Shadow DOM_ and therefore encapsulate the
|
|
159
|
-
element and styles from the rest of the document. For more information on shadow DOM
|
|
160
|
-
see [Using shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
|
|
132
|
+
When set to `true` the element will render the template (if provided) in the _Shadow DOM_ and therefore encapsulate the element and styles from the rest of the document. For more information on shadow DOM see [Using shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
|
|
161
133
|
|
|
162
134
|
#### styles
|
|
163
135
|
|
|
164
136
|
Type `array` Default: `[]`
|
|
165
137
|
|
|
166
|
-
Via the `styles` option you can add multiple styles/stylesheets to your element. For more information on styling your
|
|
167
|
-
elements see the [Styles](../features/styles.md) section.
|
|
138
|
+
Via the `styles` option you can add multiple styles/stylesheets to your element. For more information on styling your elements see the [Styles](../features/styles.md) section.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
### Element Hierarchy
|
|
3
2
|
|
|
4
3
|
Pleas keep in mind that lifecycles _do not_ wait for child elements to be connected or updated/rendered.
|
|
@@ -6,11 +5,10 @@ Pleas keep in mind that lifecycles _do not_ wait for child elements to be connec
|
|
|
6
5
|
In the example below we have a simple hierarchy of elements.
|
|
7
6
|
|
|
8
7
|
```html
|
|
9
|
-
|
|
10
8
|
<a-element>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
<b-element>
|
|
10
|
+
<c-element></c-element>
|
|
11
|
+
</b-element>
|
|
14
12
|
</a-element>
|
|
15
13
|
```
|
|
16
14
|
|
|
@@ -27,34 +25,34 @@ This loading/connecting behaviour is compliant with how other (normal) DOM eleme
|
|
|
27
25
|
In the example we render a clock and update the time every second.
|
|
28
26
|
|
|
29
27
|
```javascript
|
|
30
|
-
import {TemplateElement, defineElement, html} from '@webtides/element-js';
|
|
28
|
+
import { TemplateElement, defineElement, html } from '@webtides/element-js';
|
|
31
29
|
|
|
32
30
|
export class ClockElement extends TemplateElement {
|
|
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
|
-
|
|
31
|
+
timer = null;
|
|
32
|
+
|
|
33
|
+
properties() {
|
|
34
|
+
return {
|
|
35
|
+
time: Date.now()
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
connected() {
|
|
40
|
+
this.timer = window.setInterval(() => {
|
|
41
|
+
this.time = Date.now();
|
|
42
|
+
}, 1000);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
disconnected() {
|
|
46
|
+
window.clearInterval(this.timer);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get formattedTime() {
|
|
50
|
+
return new Date(this.time).toLocaleTimeString();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
template() {
|
|
54
|
+
return html` <span>${this.formattedTime}</span> `;
|
|
55
|
+
}
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
defineElement('clock-element', ClockElement);
|
|
@@ -1,45 +1,31 @@
|
|
|
1
|
-
|
|
2
1
|
### Lifecycle
|
|
3
2
|
|
|
4
|
-
Elements have several lifecycle methods which can be used to hook into different moments. By implementing one of the
|
|
5
|
-
following methods within the class the element will call them in the right order:
|
|
3
|
+
Elements have several lifecycle methods which can be used to hook into different moments. By implementing one of the following methods within the class the element will call them in the right order:
|
|
6
4
|
|
|
7
5
|
#### connected
|
|
8
6
|
|
|
9
|
-
Called when the element is connected to the DOM and _element-js_ is done initialising. Usually this hook will only be
|
|
10
|
-
called once for the lifetime of your element.
|
|
7
|
+
Called when the element is connected to the DOM and _element-js_ is done initialising. Usually this hook will only be called once for the lifetime of your element.
|
|
11
8
|
|
|
12
|
-
> Please note that the `connected` hook however /can/ be called more than once after the first time. It will also be
|
|
13
|
-
> invoked when the element is _attached_ or _moved_ in the DOM or to another DOM.
|
|
9
|
+
> Please note that the `connected` hook however /can/ be called more than once after the first time. It will also be invoked when the element is _attached_ or _moved_ in the DOM or to another DOM.
|
|
14
10
|
|
|
15
11
|
Use it to initialise the element and set public or "private" properties, query for other DOM elements, etc.
|
|
16
12
|
|
|
17
13
|
#### beforeUpdate
|
|
18
14
|
|
|
19
|
-
Called when the element is about to be updated. Whenever a /reactive/ property changed, the element will undergo an
|
|
20
|
-
update/render cycle. In this hook you can prepare any internal state that might be needed before the update or render
|
|
21
|
-
actually happens.
|
|
15
|
+
Called when the element is about to be updated. Whenever a /reactive/ property changed, the element will undergo an update/render cycle. In this hook you can prepare any internal state that might be needed before the update or render actually happens.
|
|
22
16
|
|
|
23
|
-
> Although the element will update/render after connecting to the DOM, the `beforeUpdate` hook won't be called for the
|
|
24
|
-
> first time. Only on subsequent update cycles.
|
|
17
|
+
> Although the element will update/render after connecting to the DOM, the `beforeUpdate` hook won't be called for the first time. Only on subsequent update cycles.
|
|
25
18
|
|
|
26
|
-
Property changes in this callback will not be applied in the current frame. They will be queued and processed in the
|
|
27
|
-
next frame.
|
|
19
|
+
Property changes in this callback will not be applied in the current frame. They will be queued and processed in the next frame.
|
|
28
20
|
|
|
29
21
|
#### afterUpdate
|
|
30
22
|
|
|
31
|
-
Called after the element was updated/rendered. Implement this hook to perform any tasks that need to be done afterwards
|
|
32
|
-
like setting/toggling classes on child elements or invoking API methods on other elements.
|
|
23
|
+
Called after the element was updated/rendered. Implement this hook to perform any tasks that need to be done afterwards like setting/toggling classes on child elements or invoking API methods on other elements.
|
|
33
24
|
|
|
34
25
|
#### disconnected
|
|
35
26
|
|
|
36
|
-
Called just before the element is about to be disconnected/removed from the DOM. Use this hook to clear or remove
|
|
37
|
-
everything that might be heavy on the browser like expensive event listeners etc.
|
|
27
|
+
Called just before the element is about to be disconnected/removed from the DOM. Use this hook to clear or remove everything that might be heavy on the browser like expensive event listeners etc.
|
|
38
28
|
|
|
39
29
|
_DISCALIMER_
|
|
40
30
|
|
|
41
|
-
The lifecycle hooks described here are custom methods provided by _element-js_. By default custom elements also have two
|
|
42
|
-
baked in hooks. `connectedCallback()` and `disconnectedCallback()`. We would encourage you to avoid these if possible.
|
|
43
|
-
Internally we use them of course to connect the element and trigger the `connected()` callback afterwards. We use them
|
|
44
|
-
to initialise the elements with all the boilerplate and prepare the API that _element-js_ provides. If you absolutely
|
|
45
|
-
must use one of them please keep in mind to call the original callback on the `super` element.
|
|
31
|
+
The lifecycle hooks described here are custom methods provided by _element-js_. By default custom elements also have two baked in hooks. `connectedCallback()` and `disconnectedCallback()`. We would encourage you to avoid these if possible. Internally we use them of course to connect the element and trigger the `connected()` callback afterwards. We use them to initialise the elements with all the boilerplate and prepare the API that _element-js_ provides. If you absolutely must use one of them please keep in mind to call the original callback on the `super` element.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
1
|
### Reactivity
|
|
3
2
|
|
|
4
|
-
_element-js_ elements update asynchronously when attributes or reactive properties are changed. Changes will also be
|
|
5
|
-
batched if multiple updates occur. The update itself will always happen in the following frame.
|
|
3
|
+
_element-js_ elements update asynchronously when attributes or reactive properties are changed. Changes will also be batched if multiple updates occur. The update itself will always happen in the following frame.
|
|
6
4
|
|
|
7
5
|
An update lifecycle roughly looks like this:
|
|
8
6
|
|
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
## Computed properties
|
|
2
2
|
|
|
3
|
-
Sometimes it is necessary to compute properties out of multiple other properties. You can simply define a getter on the
|
|
4
|
-
element and return a value.
|
|
3
|
+
Sometimes it is necessary to compute properties out of multiple other properties. You can simply define a getter on the element and return a value.
|
|
5
4
|
|
|
6
5
|
```javascript
|
|
7
6
|
export class MyElement extends BaseElement {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
properties() {
|
|
8
|
+
return {
|
|
9
|
+
reactivePublicProperty: 'I am public & reactive'
|
|
10
|
+
};
|
|
11
|
+
}
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
get computedProperty() {
|
|
14
|
+
return this.reactivePublicProperty + ' & computed';
|
|
15
|
+
}
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
log() {
|
|
18
|
+
console.log(this.computedProperty);
|
|
19
|
+
}
|
|
21
20
|
}
|
|
22
21
|
```
|
|
23
22
|
|
|
24
23
|
For every subsequent update/render cycle a computed property will be evaluated again.
|
|
25
24
|
|
|
26
|
-
> Keep in mind that properties (public or private) that are not declared via the `properties()` map will not trigger an
|
|
27
|
-
> update/render cycle when changed. If you use only non reactive properties to compute a property, it will not be
|
|
28
|
-
> re-evaluated automatically.
|
|
25
|
+
> Keep in mind that properties (public or private) that are not declared via the `properties()` map will not trigger an update/render cycle when changed. If you use only non reactive properties to compute a property, it will not be re-evaluated automatically.
|
|
@@ -3,130 +3,118 @@
|
|
|
3
3
|
_element-js_ provides a simple way of Dependency Injection following the idea of the Context [Protocol Proposal](https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md).
|
|
4
4
|
|
|
5
5
|
#### Problem "Prop Drilling"
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
If Data has to be passed down the DOM Tree to descending Child Elements it is usually done by assigning data to the descendants attributes:
|
|
8
8
|
|
|
9
9
|
```js
|
|
10
10
|
export class PropDrilling extends TemplateElement {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
11
|
+
properties() {
|
|
12
|
+
return {
|
|
13
|
+
data: { some: 'data', which: 'bloats', the: 'attributes', in: 'DOM' }
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
template() {
|
|
18
|
+
return html`
|
|
19
|
+
<!-- child element uses the same exacte data-set as the parent does -->
|
|
20
|
+
<child-element redundant-data="${data}">
|
|
21
|
+
<!-- grand child component uses parts of the parents or even the root elements dataset -->
|
|
22
|
+
<grand-child-element in-data="${data.in}"></grand-child-element>
|
|
23
|
+
</child-element>
|
|
24
|
+
<!-- child component uses parts of the parents dataset -->
|
|
25
|
+
<another-child-element some-data="${data.some}" the-data="${data.the}"></another-child-element>
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
While this is possible and totally fine for primitive values it can get confusing very fast with a deep nesting and complex data structures.
|
|
32
|
-
|
|
31
|
+
While this is possible and totally fine for primitive values it can get confusing very fast with a deep nesting and complex data structures. It also bloats up the DOM Tree as redundant data ist being passed to multiple descending Elements being copied along the way.
|
|
32
|
+
|
|
33
|
+
#### Dependency Injection for the rescue
|
|
33
34
|
|
|
34
|
-
#### Dependency Injection for the rescue
|
|
35
|
-
|
|
36
35
|
To address the issues caused by "Prop Drilling" _element-js_ provides a simple Dependency Injection Implementation following the idea of the Context Protocol mentioned above.
|
|
37
36
|
|
|
38
37
|
##### Provide via provideProperties()
|
|
39
38
|
|
|
40
|
-
An Element can control whatever is to be "provided" to requesting Elements by implementing the provideProperties function provided by the `BaseElement`.
|
|
39
|
+
An Element can control whatever is to be "provided" to requesting Elements by implementing the provideProperties function provided by the `BaseElement`.
|
|
41
40
|
|
|
42
41
|
```js
|
|
43
|
-
|
|
44
42
|
export class AncestorElement extends TemplateElement {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
43
|
+
properties() {
|
|
44
|
+
return {
|
|
45
|
+
data: { some: 'data', which: 'bloats', the: 'attributes', in: 'DOM' }
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
provideProperties() {
|
|
49
|
+
return {
|
|
50
|
+
data: this.data,
|
|
51
|
+
in: this.data.in,
|
|
52
|
+
static: 'string'
|
|
53
|
+
};
|
|
54
|
+
}
|
|
58
55
|
}
|
|
59
56
|
```
|
|
57
|
+
|
|
60
58
|
#### Vanilla JS Provide via Event Listener / Context Protocol
|
|
61
59
|
|
|
62
60
|
```html
|
|
63
61
|
<script>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
62
|
+
document.addEventListener('request-context', (event) => {
|
|
63
|
+
// global value
|
|
64
|
+
const vanillaValue = 'vanillaValue';
|
|
65
|
+
for (const [key, value] of Object.entries(event.detail)) {
|
|
66
|
+
if(key === 'vanillaContext') {
|
|
67
|
+
if (typeof value === 'function') {
|
|
68
|
+
// call function with context value
|
|
69
|
+
value(vanillaValue);
|
|
70
|
+
} else {
|
|
71
|
+
// assign as a property to Requestee
|
|
72
|
+
event.target[key] = vanillaValue;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
79
77
|
</script>
|
|
80
78
|
```
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
|
|
84
80
|
##### Inject Properties via injectProperties()
|
|
85
81
|
|
|
86
|
-
An Element can define injection requests by implementing the injectProperties function provided by the `BaseElement`.
|
|
87
|
-
The initial values will also function as default values and will be replaced after the injection request is fulfilled by an Ancestor that provides a property with the requested name.
|
|
88
|
-
Injected properties will automatically become reactive properties within the elements scope. DEVs do not have to care about where the Value is actually coming from.
|
|
89
|
-
It will be just there at some Point after the Injection will trigger changes / updates just like regular [properties](./properties.md)..
|
|
82
|
+
An Element can define injection requests by implementing the injectProperties function provided by the `BaseElement`. The initial values will also function as default values and will be replaced after the injection request is fulfilled by an Ancestor that provides a property with the requested name. Injected properties will automatically become reactive properties within the elements scope. DEVs do not have to care about where the Value is actually coming from. It will be just there at some Point after the Injection will trigger changes / updates just like regular [properties](./properties.md)..
|
|
90
83
|
|
|
91
84
|
```js
|
|
92
85
|
export class DescendingElement extends TemplateElement {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
86
|
+
injectProperties() {
|
|
87
|
+
return {
|
|
88
|
+
in: '',
|
|
89
|
+
data: {},
|
|
90
|
+
static: '',
|
|
91
|
+
vanillaContext: ''
|
|
92
|
+
};
|
|
93
|
+
}
|
|
102
94
|
}
|
|
103
|
-
|
|
104
95
|
```
|
|
105
96
|
|
|
106
97
|
##### Request Context Values via manual context Request
|
|
107
98
|
|
|
108
|
-
If you want more control over what happens with an injected value after the Injection you can do a manual context Request by using the builtin requestContext function of the BaseElement.
|
|
99
|
+
If you want more control over what happens with an injected value after the Injection you can do a manual context Request by using the builtin requestContext function of the BaseElement.
|
|
100
|
+
|
|
109
101
|
```js
|
|
110
102
|
export class ManualRequestElement extends TemplateElement {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
103
|
+
properties() {
|
|
104
|
+
return {
|
|
105
|
+
reversedArray: []
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
connected() {
|
|
109
|
+
this.requestContext('regularArray', (injectedArray) => {
|
|
110
|
+
// do whatever you like with the value
|
|
111
|
+
const processedArray = injectedArray.reverse();
|
|
112
|
+
// OPTIONAL assign to a property to trigger an update and render the reversed values´
|
|
113
|
+
this.reversedArray = processedArray;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
124
116
|
}
|
|
125
117
|
```
|
|
126
118
|
|
|
127
|
-
Still looking for more Information ?
|
|
119
|
+
Still looking for more Information ?
|
|
128
120
|
You might take a look at the [Test Implementation](../../test/unit/context-protocol.test.html) which should cover all cases
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
@@ -117,7 +117,7 @@ export class ShadowElement extends TemplateElement {
|
|
|
117
117
|
|
|
118
118
|
By default, _element-js_ will only apply all style elements from the global document that are present in the initial HTML. It will not observe the document for any changes regarding style elements.
|
|
119
119
|
|
|
120
|
-
> Observing global styles is done via a MutationObserver on the whole document. This might impose performance issues.
|
|
120
|
+
> Observing global styles is done via a MutationObserver on the whole document. This might impose performance issues.
|
|
121
121
|
|
|
122
122
|
To enable global style observation you can add the following (inline, sync) script block to yor HTML.
|
|
123
123
|
|
package/docs/features/methods.md
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
|
-
|
|
2
1
|
### Methods
|
|
3
2
|
|
|
4
3
|
Besides public properties you can also shape the API for your element with public methods.
|
|
5
4
|
|
|
6
5
|
```javascript
|
|
7
|
-
import {BaseElement, defineElement} from '@webtides/element-js';
|
|
6
|
+
import { BaseElement, defineElement } from '@webtides/element-js';
|
|
8
7
|
|
|
9
8
|
export class ModalElement extends BaseElement {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
open() {
|
|
10
|
+
// do the things to actually open the modal…
|
|
11
|
+
}
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
defineElement('modal-element', ModalElement);
|
|
16
15
|
```
|
|
17
16
|
|
|
18
17
|
```javascript
|
|
19
|
-
import {BaseElement, defineElement} from '@webtides/element-js';
|
|
18
|
+
import { BaseElement, defineElement } from '@webtides/element-js';
|
|
20
19
|
|
|
21
20
|
export class OtherElement extends BaseElement {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
events() {
|
|
22
|
+
return {
|
|
23
|
+
this: {
|
|
24
|
+
click: () => {
|
|
25
|
+
this.$refs.modal.open();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
defineElement('other-element', OtherElement);
|