I'm trying to work frameworkless, with pure javascript Web Components. I want my Web Components to be able to work stand-alone and be used on different sites, and yet I also want two components to be able to communicate. So they should be able to communicate without being tightly coupled.
Back when I did Angular, this was easy. I can pass objects to a component through a HTML attribute, and the component receives it as an object rather than a string. But in pure javascript, attributes are always strings. What is the right way to pass objects around, or otherwise make Web Components aware of each other and able to communicate?
With Web Components you can pass objects through attributes as you said, but you can also pass an object with a method, or throug a property (which is actually a setter method).
<my-component id="comp1"></my-component>
...
var myObject = { y:1, y:2 }
comp1.value = myObject //via property
comp1.setValue( myObject ) //via method
Here is a sample app with two native V1 Web Components. <component-1>
can talk to <component-2>
because you supply an ID into <component-1>
and that ID refers to the ID set on <component-2>
.
This is similar to how the <label>
tag work with its for
attribute.
<component-1 link-id="c2"></component-1>
<hr/>
<component-2 id="c2"></component-2>
// Class for `<component-1>`
class Component1 extends HTMLElement {
constructor() {
super();
this._linkedComponent = null;
this._input = document.createElement('input');
this._input.addEventListener('focus', this._focusHandler.bind(this));
this._button = document.createElement('button');
this._button.textContent = 'Add';
this._button.addEventListener('click', this._clickHandler.bind(this));
}
connectedCallback() {
this.appendChild(this._input);
this.appendChild(this._button);
}
static get observedAttributes() {
return ['link-id'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal) {
if (newVal === null) {
this._linkedComponent = null;
}
else {
this._linkedComponent = document.getElementById(newVal);
}
}
}
_clickHandler() {
if (this._linkedComponent) {
this._linkedComponent.value = this._input.value;
}
}
_focusHandler() {
this._input.value = '';
}
}
// Class for `<component-2>`
class Component2 extends HTMLElement {
constructor() {
super();
this._textArea = document.createElement('textarea');
this._textArea.setAttribute('style','width:100%;height:200px;');
}
connectedCallback() {
this.appendChild(this._textArea);
}
set value(newValue) {
this._textArea.value += (newValue+'\n');
}
}
customElements.define('component-1', Component1);
customElements.define('component-2', Component2);
<component-1>
will only talk to <component-2>
if there is a component with the ID that was provided to <component-1>
through its link-id
attribute.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With