Ad/iklan :

3gp Mp4 HD
Play/Download
Live 3D App
Search.Pencarian Menu

Add text send email to rh3252705.adda@blogger.com or Click this (Text porn Will delete) | Tambah teks kirim email ke rh3252705.adda@blogger.com atau Klik ini (Teks porno akan dihapus)
Total post.pos : 16329+

[Go Make Things] How would you share state between Web Components?

Yesterday, I had an interesting chat with a friend about how I would share state between Web Components, and get them to talk to each other in a web app.

Today, let's explore what that might look like!

An ecommerce platform

An example I like to use for this kind of thing is an ecommerce platform with a few interconnected components.

You might have a <cart-link> Web Component that displays a link to the checkout page, with the number of items in the cart as it's text.

<cart-link>  	<a href="/checkout">🛒 2 Items</a>  </cart-link>

You might also have a <product-listing> Web Component that displays an Add to Cart button if the item isn't in your text, or a message if it is.

<!-- Not in the cart -->  <product-listing price="39" uid="tshirt-jolly-roger">  	<button>Add to Cart - $39</button>  </product-listing>    <!-- Already in the cart -->  <product-listing price="39" uid="tshirt-jolly-roger">  	<em>This is item in your cart</em>  </product-listing>

And powering both of these Web Components is a cart variable—an object ({})—that holds the items currently in the cart.

let cart = {};  

Whenever an item is added to the cart, the <cart-link> element needs to update the text about how many items are in the cart. The <product-listing> also needs to update itself to show either a <button> or message depending on whether the item is in the cart.

Let's take a look at how to wire up all of these pieces so they can talk to each other.

A simple signal

To make this work, we'll create a Signal class that will actually hold the cart data.

Whenever the data is updated, the Signal will emit a custom event that the other Web Components can listen to. We'll start by storing whatever value is passed in to the this.value property.

class Signal {    	// Initialize the class  	constructor (val) {  		this.value = val;  	}    }  

We'll create a new Signal() for the cart like this…

let cart = new Signal({});  

Next, we'll add an add() method that accepts a key and val as arguments.

The method will add or update the key in the this.value object. Then, it will emit a custom cart-updated event.

Note: In a real production app, I'd either use setter and getter methods or Proxies for this. But this is a useful, simple model for teaching.

class Signal {    	// Initialize the class  	constructor (val) {  		this.value = val;  	}    	// Add a new item  	add (key, val) {    		// Update the value  		this.value[key] = val;    		// Create a new event  		let event = new CustomEvent('cart-updated', {  			bubbles: true,  			detail: {key, val}  		});    		// Dispatch the event  		return document.dispatchEvent(event);    	}    }  

While we're here, let's also add a size() method that returns the number of items in the this.value object, and a has() method that checks if a key is in the this.value object or not.

class Signal {    	// ...    	// Get the number of items in the cart  	size () {  		return Object.keys(this.value).length;  	}    	// Check if an item is in the object  	has (key) {  		return !!this.value[key];  	}    }  

For the <cart-link> component, we'll create a render() method that gets the cart.size(), and displays it as a link inside the custom element.

customElements.define('cart-link', class extends HTMLElement {    	// Instantiate the Web Component  	constructor () {    		// Inherit parent class properties  		super();    		// Render the initial UI  		this.render();    	}    	// Render the UI  	render () {  		this.innerHTML = `<a href="/checkout">🛒 ${cart.size()} Items</a>`;  	}    });  

We'll add an event listener for the cart-updated event, and use the handleEvent() method to run the render() method whenever the cart is updated.

customElements.define('cart-link', class extends HTMLElement {    	// Instantiate the Web Component  	constructor () {    		// Inherit parent class properties  		super();    		// Render the initial UI  		this.render();    		// Listen for cart events  		document.addEventListener('cart-updated', this);    	}    	// Handle Events  	handleEvent (event) {  		this.render();  	}    	// Render the UI  	render () {  		this.innerHTML = `<a href="/checkout">🛒 ${cart.size()} Items</a>`;  	}    });  

Now, whenever the cart is updated, the <cart-link> gets updated automatically.

🧐 Want to learn more about Web Components? I'm adding all of my guides around building Web Components to my members-only toolkit. Joining is a great way to support my work!

Creating the <product-listing> component

We'll do something similar for the <product-listing> Web Component.

When the Web Component instantiates, we'll use the Element.getAttribute() method to get the [uid] and [price] attributes, and save them to properties.

Then well run a render() method to render the UI.

customElements.define('product-listing', class extends HTMLElement {    	/**  	 * Instantiate the Web Component  	 */  	constructor () {    		// Inherit parent class properties  		super();    		// Set properties  		this.uid = this.getAttribute('uid');  		this.price = parseFloat(this.getAttribute('price'));    		// Render the initial UI  		this.render();    	}    });  

Inside the render() method, we'll use the cart.has() method to check if this.uid is in the cart already.

If it is, we'll show a message. If not, we'll show a button to add the item to the cart, with this.price as part of the button text.

// Render the UI  render () {  	this.innerHTML = cart.has(this.uid) ? '<em>This is item in your cart</em>' : `<button>Add to Cart - $${this.price}</button>`;  }  

Next, we'll add an event listener for the cart-updated event. We'll also listen for click events inside the custom element.

/**   * Instantiate the Web Component   */  constructor () {    	// Inherit parent class properties  	super();    	// Set properties  	this.uid = this.getAttribute('uid');  	this.price = parseFloat(this.getAttribute('price'));    	// Render the initial UI  	this.render();    	// Listen for events  	document.addEventListener('cart-updated', this);  	this.addEventListener('click', this);    }  

Inside the handleEvent() method, we'll check if the event.type is cart-updated.

If so, we'll run the render() method to update the UI, and return to end the function. If the event.type is click, and the event.target (the clicked element) is or is inside a button, we'll run the cart.add() method to add this.uid to the cart object.

// Handle events  handleEvent (event) {    	// If it's a cart update event  	if (event.type === 'cart-updated') {  		this.render();  		return;  	}    	// If it's a click on the button  	if (event.type === 'click' && event.target.closest('button')) {  		cart.add(this.uid, this.price);  	}    }  

Adding the item will trigger the cart-updated event, which will trigger a render of the UI.

Putting it all together

Here's a demo you can use to play around with this idea. And if you'd prefer, here's the downloadable source code on GitHub.

Depending on the use case, there are other ways you might handle this kind of thing. But this would probably be my starting point for an app like this.

Like this? A Go Make Things membership is the best way to support my work and help me create more free content.

Cheers,
Chris

Want to share this with others or read it later? View it in a browser.

Share :

Facebook Twitter Google+
0 Komentar untuk "[Go Make Things] How would you share state between Web Components?"

Back To Top