Skip to content

Commit

Permalink
track and document caveats with inferredObservability targeting
Browse files Browse the repository at this point in the history
  • Loading branch information
thescientist13 committed Jan 9, 2024
1 parent 4a7509b commit 83ea8f1
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 21 deletions.
12 changes: 6 additions & 6 deletions docs/pages/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,9 @@ customElements.define('wcc-counter', Counter);
### (Inferred) Attribute Observability
An optional feature supported by JSX based compilation is a feature called `inferredObservability`. With this enabled, WCC will read any `this` member references in your component's `render` function and map each member instance to
- an entry in the `observedAttributes` array
- automatically handle `attributeChangedCallback` update (by calling `this.render()`)
An optional feature supported by JSX based compilation is `inferredObservability`. With this enabled, WCC will read any `this` member references in your component's `render` function and map each member instance to
1. an entry in the `observedAttributes` array
1. automatically handle `attributeChangedCallback` updates

So taking the above counter example, and opting in to this feature, we just need to enable the `inferredObservability` option in the component
```jsx
Expand All @@ -334,6 +334,7 @@ export default class Counter extends HTMLElement {
return (
<div>
<button onclick={this.count -= 1}> -</button>
<!-- note that {count} has to be wrapped in its own HTML tag -->
<span>You have clicked <span class="red">{count}</span> times</span>
<button onclick={this.increment}> +</button>
</div>
Expand All @@ -348,6 +349,5 @@ And so now when the attribute is set on this component, the component will re-re
```
Some notes / limitations:
- Please be aware of the above linked discussion which is tracking known bugs / feature requests / open items related to all things WCC + JSX.
- We consider the capability of this observability to be "coarse grained" at this time since WCC just re-runs the entire `render` function, replacing of the `innerHTML` for the host component. Thought it is still WIP, we are exploring a more ["fine grained" approach](https://github.com/ProjectEvergreen/wcc/issues/108) that will more efficient than blowing away all the HTML, a la in the style of [**lit-html**](https://lit.dev/docs/templates/overview/) or [**Solid**'s Signals](https://www.solidjs.com/tutorial/introduction_signals).
- This automatically _reflects properties used in the `render` function to attributes_, so YMMV.
- Please be aware of the above linked discussion and issue filter which is tracking any known bugs / feature requests / open items related to all things WCC + JSX.
- This automatically reflects properties used in the `render` function to attributes, so [YMMV](https://dictionary.cambridge.org/us/dictionary/english/ymmv).
2 changes: 1 addition & 1 deletion sandbox/components/counter-dsd.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default class CounterDsdJsx extends HTMLElement {
connectedCallback() {
if (!this.shadowRoot) {
console.warn('NO shadowRoot detected for counter-dsd.jsx!');
this.count = this.getAttribute('count') || 0;
this.count = parseInt(this.getAttribute('count'), 10) || 0;

// having an attachShadow call is required for DSD
this.attachShadow({ mode: 'open' });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
attributeChangedCallback(name, oldValue, newValue) {
function getValue(value) {
return value.charAt(0) === '{' || value.charAt(0) === '[' ? JSON.parse(value) : !isNaN(value) ? parseInt(value, 10) : value === 'true' || value === 'false' ? value === 'true' ? true : false : value;
}
if (newValue !== oldValue) {
switch (name) {
case 'count':
this.count = getValue(newValue);
break;
}
this.render();
}
function getValue(value) {
return value.charAt(0) === '{' || value.charAt(0) === '[' ? JSON.parse(value) : !isNaN(value) ? parseInt(value, 10) : value === 'true' || value === 'false' ? value === 'true' ? true : false : value;
}
if (newValue !== oldValue) {
switch (name) {
case 'count':
this.count = getValue(newValue);
break;
}
this.update(name, oldValue, newValue);
}
}
update(name, oldValue, newValue) {
console.debug('Update tracking against....', this.constructor.observedAttributes);
console.debug('Updating', name);
console.debug('Swap old', oldValue);
console.debug('For new', newValue);
console.debug('this[name]', this[name]);
const attr = `data-wcc-${ name }`;
const selector = `[${ attr }]`;
console.debug({ attr });
console.debug({ selector });
this.querySelectorAll(selector).forEach(el => {
const needle = oldValue || el.getAttribute(attr);
console.debug({ el });
console.debug({ needle });
console.debug({ newValue });
switch (el.getAttribute('data-wcc-ins')) {
case 'text':
el.textContent = el.textContent.replace(needle, newValue);
break;
case 'attr':
if (el.hasAttribute(el.getAttribute(attr))) {
el.setAttribute(el.getAttribute(attr), newValue);
}
break;
}
});
if (['count'].includes(name)) {
}
console.debug('****************************');
}
2 changes: 1 addition & 1 deletion test/cases/jsx-shadow-dom/src/heading.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class HeadingComponent extends HTMLElement {

return (
<div>
<h1>Hello, {greeting}!</h1>
<h1>Hello, <span>{greeting}</span>!</h1>
<button onclick={this.sayHello}>Get a greeting!</button>
</div>
);
Expand Down
3 changes: 2 additions & 1 deletion test/cases/jsx/jsx.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('Run WCC For ', function() {
before(async function() {
const { html, metadata } = await renderToString(new URL('./src/counter.jsx', import.meta.url));

console.log({ html });
meta = metadata;
dom = new JSDOM(html);
});
Expand Down Expand Up @@ -69,7 +70,7 @@ describe('Run WCC For ', function() {
it('should handle an assignment expression with implicit reactivity using this.render', () => {
const element = Array.from(buttons).find(button => button.getAttribute('id') === 'evt-assignment');

expect(element.getAttribute('onclick')).to.be.equal('this.parentElement.parentElement.count-=1; this.parentElement.parentElement.render();');
expect(element.getAttribute('onclick')).to.be.equal('this.parentElement.parentElement.count-=1; this.parentElement.parentElement.setAttribute(\'count\', this.parentElement.parentElement.count);');

Check failure on line 73 in test/cases/jsx/jsx.spec.js

View workflow job for this annotation

GitHub Actions / build (20)

This line has a length of 206. Maximum allowed is 200

Check failure on line 73 in test/cases/jsx/jsx.spec.js

View workflow job for this annotation

GitHub Actions / build (20)

This line has a length of 206. Maximum allowed is 200

Check failure on line 73 in test/cases/jsx/jsx.spec.js

View workflow job for this annotation

GitHub Actions / build (18)

This line has a length of 206. Maximum allowed is 200

Check failure on line 73 in test/cases/jsx/jsx.spec.js

View workflow job for this annotation

GitHub Actions / build (18)

This line has a length of 206. Maximum allowed is 200

Check failure on line 73 in test/cases/jsx/jsx.spec.js

View workflow job for this annotation

GitHub Actions / build (20)

This line has a length of 206. Maximum allowed is 200

Check failure on line 73 in test/cases/jsx/jsx.spec.js

View workflow job for this annotation

GitHub Actions / build (20)

This line has a length of 206. Maximum allowed is 200
});
});

Expand Down
2 changes: 1 addition & 1 deletion test/cases/jsx/src/badge.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default class BadgeComponent extends HTMLElement {
const conditionalText = predicate ? ' 🥳' : '';

return (
<span class={conditionalClass}>{count}{conditionalText}</span>
<span class={conditionalClass}><span>{count}</span>{conditionalText}</span>
);
}
}
Expand Down

0 comments on commit 83ea8f1

Please sign in to comment.