Skip to content

Instantly share code, notes, and snippets.

@iamspark1e
Last active November 1, 2023 03:38
Show Gist options
  • Save iamspark1e/cfc03b6a20d1a323bea3b98ca2821900 to your computer and use it in GitHub Desktop.
Save iamspark1e/cfc03b6a20d1a323bea3b98ca2821900 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@2.8.2/dist/alpine.min.js"></script>
</head>
<body>
<alpine-wc-tree id="delay-start"></alpine-wc-tree>
<alpine-wc-tree init-value="500"></alpine-wc-tree>
<script>
const template = document.createElement("template");
template.innerHTML = `
<style>
span, button {
font-size: 200%;
}
span {
width: 4rem;
display: inline-block;
text-align: center;
}
button {
width: 4rem;
height: 4rem;
border: none;
border-radius: 10px;
background-color: seagreen;
color: white;
}
</style>
<div x-data="$el.parentElement.data" @outside-updater="updater">
<button @click="dec()">-</button>
<span x-text="count"></span>
<button @click="inc()">+</button>
</div>
`;
class AlpineWCTreeComponent extends HTMLElement {
data = {
count: 0,
inc() {
this.count++;
},
dec() {
this.count--;
},
updater(event) {
this.count = event.detail.count;
}
};
constructor() {
super();
this.init();
this.append(template.content.cloneNode(true));
this.addEventListener('outside-updater', this.passEventHelper) // internal custom event bridge, pass outer event.
// Otherwise, you can use `@xxxx.window` instead. (But affect global, not recommand).
}
passEventHelper(e) {
let payload = e.detail;
Array.from(e.target.children).forEach(node => node.dispatchEvent(new CustomEvent('outside-updater', { detail: payload })));
}
init() {
this.data.count = parseInt(this.getAttribute('init-value') || 0)
}
}
</script>
<script>
customElements.define("alpine-wc-tree", AlpineWCTreeComponent);
setTimeout(() => {
let wc = document.getElementById("delay-start")
wc.dispatchEvent(new CustomEvent('outside-updater', { detail: { count: 2000 } })) // simulate async data change
}, 2000)
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- WARNING: this example only works with Alpinejs v3+ -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<!-- <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@2.8.2/dist/alpine.min.js"></script> -->
</head>
<body>
<alpine-wc-tree id="delay-start"></alpine-wc-tree>
<alpine-wc-tree init-value="500"></alpine-wc-tree>
<script>
const template = document.createElement("template");
template.innerHTML = `
<style>
span, button {
font-size: 200%;
}
span {
width: 4rem;
display: inline-block;
text-align: center;
}
button {
width: 4rem;
height: 4rem;
border: none;
border-radius: 10px;
background-color: seagreen;
color: white;
}
</style>
<div @outside-updater.window="updater">
<button @click="dec()">-</button>
<span x-text="count"></span>
<button @click="inc()">+</button>
</div>
`;
class AlpineWCTreeComponent extends HTMLElement {
data = {
count: 0,
inc() {
this.count++;
},
dec() {
this.count--;
},
updater(event) {
console.log(event);
this.count = event.detail.count;
}
};
constructor() {
super();
this.init();
// this.addEventListener('outside-updater', this.passEventHelper) // internal custom event bridge, pass outer event.
// Otherwise, you can use `@xxxx.window` instead. (But affect global, not recommand).
}
// Scoped event handler seems not work with "closed" component.
// passEventHelper(e) {
// console.log(e);
// let payload = e.detail;
// Array.from(e.target.children).forEach(node => node.dispatchEvent(new CustomEvent('outside-updater', { detail: payload })));
// }
init() {
this.data.count = parseInt(this.getAttribute('init-value') || 0)
}
connectedCallback() {
this._root = this.attachShadow({ mode: 'closed' });
this._root.appendChild(template.content.cloneNode(true));
document.addEventListener(
'alpine:initialized',
() => {
Alpine.addScopeToNode(this._root, Alpine.reactive(this.data))
Alpine.initTree(this._root);
}
)
}
}
</script>
<script>
customElements.define("alpine-wc-tree", AlpineWCTreeComponent);
setTimeout(() => {
// let wc = document.getElementById("delay-start")
window.dispatchEvent(new CustomEvent('outside-updater', { detail: { count: 2000 } })) // simulate async data change, all component will receive this and update count.
}, 2000)
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment