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" ? ". ðŸ˜" : "! 🙌"
+ }
`;
}
}