diff --git a/docs/pages/docs.md b/docs/pages/docs.md
index d4434b4..8e7a9c2 100644
--- a/docs/pages/docs.md
+++ b/docs/pages/docs.md
@@ -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
@@ -334,6 +334,7 @@ export default class Counter extends HTMLElement {
return (
+
You have clicked {count} times
@@ -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).
diff --git a/sandbox/components/counter-dsd.jsx b/sandbox/components/counter-dsd.jsx
index 26c7a53..6f1d230 100644
--- a/sandbox/components/counter-dsd.jsx
+++ b/sandbox/components/counter-dsd.jsx
@@ -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' });
diff --git a/test/cases/jsx-inferred-observability/fixtures/attribute-changed-callback.txt b/test/cases/jsx-inferred-observability/fixtures/attribute-changed-callback.txt
index 3801a39..87fb721 100644
--- a/test/cases/jsx-inferred-observability/fixtures/attribute-changed-callback.txt
+++ b/test/cases/jsx-inferred-observability/fixtures/attribute-changed-callback.txt
@@ -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('****************************');
}
\ No newline at end of file
diff --git a/test/cases/jsx-shadow-dom/src/heading.jsx b/test/cases/jsx-shadow-dom/src/heading.jsx
index 68f6d1b..cd97a2b 100644
--- a/test/cases/jsx-shadow-dom/src/heading.jsx
+++ b/test/cases/jsx-shadow-dom/src/heading.jsx
@@ -17,7 +17,7 @@ export default class HeadingComponent extends HTMLElement {
return (
-
Hello, {greeting}!
+
Hello, {greeting}!
);
diff --git a/test/cases/jsx/jsx.spec.js b/test/cases/jsx/jsx.spec.js
index 981e429..f22686e 100644
--- a/test/cases/jsx/jsx.spec.js
+++ b/test/cases/jsx/jsx.spec.js
@@ -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);
});
@@ -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);');
});
});
diff --git a/test/cases/jsx/src/badge.jsx b/test/cases/jsx/src/badge.jsx
index 4251609..8f9bd08 100644
--- a/test/cases/jsx/src/badge.jsx
+++ b/test/cases/jsx/src/badge.jsx
@@ -33,7 +33,7 @@ export default class BadgeComponent extends HTMLElement {
const conditionalText = predicate ? ' 🥳' : '';
return (
- {count}{conditionalText}
+ {count}{conditionalText}
);
}
}