diff --git a/README.md b/README.md index 6784844..7977b3f 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,9 @@ The result is a reactive UI on property changes. 1. [Usage](#usage) 1. [Quick Start Example](#quick-start-example) 😉 1. [Life-Cycle Hooks](#life-cycle-hooks) - 1. [`onInit`](#oninit) - the component is connected to the DOM - 1. [`onChanges`](#onchanges) - an attribute value changed + 1. [`onInit`](#oninit) - the component is connected to the DOM, before view is initialized + 1. [`afterViewInit`](#afterviewinit) - after the view is first initialized + 1. [`onChanges`](#onchanges) - every time an attribute value changes ## Vanilla JS import Import using [unpkg](https://unpkg.com/web-component-base) in your component. We will use this in the rest of our [usage examples](#usage). @@ -128,7 +129,7 @@ Here is an example of using a custom element in a single .html file: Define behavior when certain events in the component's life cycle is triggered by providing hook methods ### onInit() -- gets triggered when the component is connected to the DOM +- triggered when the component is connected to the DOM - best for setting up the component ```js @@ -146,8 +147,25 @@ class ClickableText extends WebComponent { } ``` +### afterViewInit() +- triggered after the view is first initialized + +```js +class ClickableText extends WebComponent { + // gets called when the component's innerHTML is first filled + afterViewInit() { + const footer = this.querySelector('footer'); + // do stuff to footer after view is initialized + } + + get template() { + return ``; + } +} +``` + ### onChanges() -- gets triggered when an attribute value changed +- triggered when an attribute value changed ```js import WebComponent from "https://unpkg.com/web-component-base"; diff --git a/WebComponent.mjs b/WebComponent.mjs index 770cdf5..96dfe85 100644 --- a/WebComponent.mjs +++ b/WebComponent.mjs @@ -17,26 +17,38 @@ export class WebComponent extends HTMLElement { return this.properties; } + /** + * triggered after view is initialized + */ + afterViewInit() {} + /** * triggered when the component is connected to the DOM */ onInit() {} /** - * triggered when an attribute value changed + * @template {{'previousValue': any, 'currentValue': any}} SimpleChange + * @param {Record} changes */ - onChanges({ property, previousValue, currentValue }) {} + onChanges(changes) {} connectedCallback() { - this.render(); this.onInit(); + this.render(); + this.afterViewInit(); } + /** + * @param {string} property + * @param {any} previousValue + * @param {any} currentValue + */ attributeChangedCallback(property, previousValue, currentValue) { if (previousValue !== currentValue) { this[property] = currentValue; - this.onChanges({ property, previousValue, currentValue }); this.render(); + this.onChanges({ [property]: { previousValue, currentValue } }); } } diff --git a/demo/HelloWorld.mjs b/demo/HelloWorld.mjs index 5e055eb..e927373 100644 --- a/demo/HelloWorld.mjs +++ b/demo/HelloWorld.mjs @@ -7,13 +7,26 @@ export class HelloWorld extends WebComponent { static properties = ["name", "emotion"]; - onChanges({ property, previousValue, currentValue }) { - console.log(">>> changed", { property, previousValue, currentValue }); + onInit() { + console.log("onInit", this.querySelector("h1")); + } + + afterViewInit() { + console.log("afterViewInit", this.querySelector("h1")); + } + + onChanges(changes) { + Object.keys(changes).forEach((name) => { + console.log( + `${name} changed from ${changes[name].previousValue} to ${changes[name].currentValue}` + ); + }); } get template() { - return ` -

Hello ${this.name}${this.emotion === "sad" ? ". 😭" : "! 🙌"}

`; + return `

Hello ${this.name}${ + this.emotion === "sad" ? ". 😭" : "! 🙌" + }

`; } }