<input type="text" id="newItem">
<button id="addItem">Add Item</button>
<div>Total items: <span id="itemCountEl">0</span></div>
<ul id="itemListEl"></ul>
// Classess
class Observable {
#value;
#subscribers = [];
constructor(value) {
this.#value = value;
}
get value() {
return this.#value;
}
set value(newValue) {
this.#value = newValue;
this.notify();
}
subscribe(observer) {
this.#subscribers.push(observer);
}
unsubscribe(observer) {
this.#subscribers = this.#subscribers.filter(sub => sub !== observer);
}
notify() {
this.#subscribers.forEach(subscriber => subscriber(this.#value));
}
}
class Computed extends Observable {
#dependencies;
constructor(computeFunc, dependencies) {
// Call the Observable constructor with the initial computed value
super(computeFunc());
this.#dependencies = dependencies;
// Define listner to run on dependencies change
const listner = () => {
this.value = computeFunc(); // Compute again
};
// Subscribe to each dependency and run the listner
this.#dependencies.forEach(dep => dep.subscribe(listner));
}
}
// Cart Logic
const itemList = new Observable([]);
const itemCount = new Computed(() => itemList.value.length, [itemList]);
addItem.addEventListener('click', () => {
if (newItem) {
itemList.value = [itemList.value, newItem.value]; // Add the new item
newItem.value = ''; // Reset input field
}
});
// Subscribe to update the UI whenever itemCount changes
itemCount.subscribe(count => {
itemCountEl.textContent = count;
itemListEl.innerHTML = itemList.value.map(item => `<li>${item}</li>`).join('');
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.