Created
March 4, 2020 22:16
-
-
Save justinfagnani/d7f73971bfa3c96d5a08f9dadda6ea08 to your computer and use it in GitHub Desktop.
Observable LitElement
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 ExampleElement extends ObservableLitElement { | |
@property() | |
src: string; | |
@observe('src') | |
protected async _onSrcChange() { | |
// fetch the new URL... | |
} | |
} |
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
/** | |
* @license | |
* Copyright (c) 2020 The Polymer Project Authors. All rights reserved. | |
* This code may only be used under the BSD style license found at | |
* http://polymer.github.io/LICENSE.txt | |
* The complete set of authors may be found at | |
* http://polymer.github.io/AUTHORS.txt | |
* The complete set of contributors may be found at | |
* http://polymer.github.io/CONTRIBUTORS.txt | |
* Code distributed by Google as part of the polymer project is also | |
* subject to an additional IP rights grant found at | |
* http://polymer.github.io/PATENTS.txt | |
*/ | |
import {LitElement, PropertyValues} from 'lit-element'; | |
export * from 'lit-element'; | |
export type Observer = () => void; | |
export interface ObservableLitElementConstructor { | |
new (): ObservableLitElement; | |
_observers: Map<PropertyKey, Observer[]>; | |
} | |
export abstract class ObservableLitElement extends LitElement { | |
update(changedProperties: PropertyValues) { | |
const clazz = this.constructor as ObservableLitElementConstructor; | |
if (clazz._observers !== undefined) { | |
// Collect all observers triggered by this batch of property changes | |
const observersToRun = new Set<Observer>(); | |
for (const propertyName of changedProperties.keys()) { | |
const observers = clazz._observers.get(propertyName); | |
if (observers !== undefined) { | |
for (const observer of observers) { | |
observersToRun.add(observer); | |
} | |
} | |
} | |
// Run the observers | |
for (const observer of observersToRun) { | |
observer.call(this); | |
} | |
} | |
super.update(changedProperties); | |
} | |
} | |
export function observe(...propertyNames: string[]) { | |
return (proto: any, method: string) => { | |
const clazz = proto.constructor as DesignerElementConstructor; | |
if (!clazz.hasOwnProperty('_observers')) { | |
Object.defineProperty(clazz, '_observers', {value: new Map()}); | |
} | |
for (const property of propertyNames) { | |
let observers = clazz._observers.get(property); | |
observers ?? clazz._observers.set(property, (observers = [])); | |
observers.push(clazz.prototype[method]); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Does this support stuff like src.* too? E.g. sub properties?