Last active
January 30, 2023 04:01
-
-
Save dliebner/d745f83e1df467a2f12747aba6fb2dcf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Notifies ancestor of drilled property update via event | |
*/ | |
class DrilledPropertyUpdateEventController { | |
static customEventName = 'lit-drilled-property-update'; | |
/** @type {HTMLElement} */ | |
host; | |
/** | |
* @param {ControllerHost} host | |
* @param {string} drilledProperty | |
*/ | |
constructor(host, drilledProperty) { | |
// Store a reference to the host | |
this.host = host; | |
// Register for lifecycle updates | |
host.addController(this); | |
/** @type {string} */ | |
this.drilledProperty = drilledProperty; | |
} | |
/** @param {CustomEvent} e */ | |
_handleCustomEvent = (e) => { | |
if( e.detail.drilledProperty === this.drilledProperty ) { | |
e.stopPropagation(); | |
if( e.detail.proxiedUpdate ) { | |
// newValue is a callback | |
this.host[this.drilledProperty] = e.detail.newValue( this.host[this.drilledProperty] ); | |
} else { | |
// newValue is the new value | |
this.host[this.drilledProperty] = e.detail.newValue; | |
} | |
} | |
}; | |
hostConnected() { | |
this.host.addEventListener(this.constructor.customEventName, this._handleCustomEvent); | |
} | |
hostDisconnected() { | |
this.host.removeEventListener(this.constructor.customEventName, this._handleCustomEvent); | |
} | |
/** | |
* @param {HTMLElement} descendantEl | |
* @param {string} drilledProperty | |
* @param {*} newValue | |
* @param {boolean} proxiedUpdate Set to true to pass a callback as newValue which accepts the drilledProperty value as a parameter and returns the mutated version | |
*/ | |
static dispatchUpdateFromDescendant( descendantEl, drilledProperty, newValue, proxiedUpdate = false ) { | |
if( proxiedUpdate && typeof newValue !== 'function' ) throw "Tried to dispatch a proxied update from descendant, but newValue was not a callback type"; | |
descendantEl.dispatchEvent( | |
new CustomEvent(this.customEventName, { | |
bubbles: true, | |
composed: true, | |
detail: { | |
drilledProperty, | |
newValue, | |
proxiedUpdate | |
} | |
}) | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ParentElementWithDrilledProperty extends LitElement { | |
static properties = { | |
foo: {state: true}, | |
}; | |
constructor() { | |
super(); | |
this.foo = { | |
bax: 'baz' | |
}; | |
/** Allows descendants to update this.foo */ | |
this.fooUpdateController = new DrilledPropertyUpdateEventController(this, 'foo'); | |
} | |
render() { | |
return html` | |
<my-child-element .foo=${this.foo}></my-child-element> | |
`; | |
} | |
} | |
customElements.define('my-parent-element', ParentElementWithDrilledProperty); | |
class ChildElementWithDrilledProperty extends LitElement { | |
static properties = { | |
foo: {state: true}, | |
}; | |
_handleClick() { | |
DrilledPropertyUpdateEventController.dispatchUpdateFromDescendant( | |
this, | |
'foo', | |
{ | |
bax: 'cool' | |
} | |
); | |
} | |
render() { | |
return html` | |
<div @click=${this._handleClick}> | |
My bax is so ${this.foo.bax}! | |
</div> | |
`; | |
} | |
} | |
customElements.define('my-child-element', ChildElementWithDrilledProperty); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment