From d65c0345628674286ea84a8a3a11b167519ccbe1 Mon Sep 17 00:00:00 2001
From: Kate Jeffreys
Date: Thu, 3 Jan 2019 13:01:42 -0800
Subject: [PATCH 1/3] Draft skeleton
---
docs/_data/guide.yml | 3 +
docs/_guide/events.md | 281 ++++++++++++++++++
.../projects/events/events/index.html | 17 ++
.../_includes/projects/events/events/index.ts | 1 +
.../projects/events/events/manifest.json | 14 +
.../projects/events/events/my-element.js | 32 ++
6 files changed, 348 insertions(+)
create mode 100644 docs/_guide/events.md
create mode 100644 docs/_includes/projects/events/events/index.html
create mode 100644 docs/_includes/projects/events/events/index.ts
create mode 100644 docs/_includes/projects/events/events/manifest.json
create mode 100644 docs/_includes/projects/events/events/my-element.js
diff --git a/docs/_data/guide.yml b/docs/_data/guide.yml
index 9068b089..90669f36 100644
--- a/docs/_data/guide.yml
+++ b/docs/_data/guide.yml
@@ -18,6 +18,9 @@ toc:
title: Properties
desc: Declare and configure a component's properties and attributes.
url: /guide/properties
+ events:
+ title: Events
+ url: /guide/events
lifecycle:
title: Lifecycle
desc: Specify when an element should update. Respond to updates, or wait for an update to complete.
diff --git a/docs/_guide/events.md b/docs/_guide/events.md
new file mode 100644
index 00000000..e9f3b648
--- /dev/null
+++ b/docs/_guide/events.md
@@ -0,0 +1,281 @@
+---
+layout: guide
+title: Events
+slug: events
+---
+
+TODO: Tidy up this page
+
+{::options toc_levels="1..3" /}
+* ToC
+{:toc}
+
+## Overview
+
+* Default event context is `this` - no need for `this.handlerMethod.bind(this)`
+* You can use `this` referring to the host inside an event handler
+* Add event listeners in a method that is guaranteed to fire before the event occurs
+* For optimal loading performance, add your event listener as late as possible
+
+## Add an event listener to a LitElement host
+
+You can use the `firstUpdated` callback to add an event listener after the element has first been rendered:
+
+```js
+class MyElement extends LitElement {
+ firstUpdated(changedProperties) {
+ this.addEventListener('click', (e) => { ... });
+})
+```
+
+```js
+class MyElement extends LitElement {
+ firstUpdated(changedProperties) {
+ this.addEventListener('click', this.clickHandler);
+ }
+ clickHandler(e) { ... }
+)
+```
+
+If your event might occur before the element has finished rendering, you can add the listener from the constructor:
+
+```js
+class MyElement extends LitElement {
+ constructor() {
+ super.constructor();
+ this.addEventListener('some-event', (e) => { ... });
+})
+```
+
+```js
+class MyElement extends LitElement {
+ constructor() {
+ super.constructor();
+ this.addEventListener('some-event', this.someEventHandler);
+ }
+ someEventHandler(e) { ... }
+)
+```
+
+## Add an event listener to the child element of a LitElement host
+
+**Option 1: Use lit-html template syntax**
+
+You can add an event listener to an element's DOM child using lit-html data binding syntax:
+
+```js
+render() {
+ return html``;
+}
+handleClick(e) {
+ // ...
+}
+```
+
+See the documentation on [Templates](templates) for more information on lit-html template syntax.
+
+**Option 2: Add the listener imperatively**
+
+To add an event listener to a child element imperatively, you must do so in or after `firstUpdated` to ensure that the child element exists. For example:
+
+```js
+render() {
+ return html``;
+}
+
+firstUpdated(changedProperties) {
+ let el = this.shadowRoot.getElementById('mybutton');
+ el.addEventListener('click', this.handleClick);
+}
+...
+handleClick(e) {
+ ...
+}
+```
+
+### Bubbling, custom events, composed path, etc
+
+**Event bubbling**
+
+```js
+//?????
+constructor() {
+ this.super();
+ this.addEventListener('click', (e) => { console.log(e.target)});
+}
+render() {
+ return html``;
+}
+handleClick(e) {
+ console.log(e.target.id);
+}
+```
+
+**Event retargeting**
+
+```js
+render() {
+ return html``;
+}
+handleClick(e) {
+ console.log(e.target.id);
+}
+```
+
+**Composed path**
+
+```js
+render() {
+ return html``;
+}
+handleClick(e) {
+ let origin = e.composedPath()[0];
+ console.log(origin.id);
+}
+```
+
+By default, custom events stop at shadow DOM boundaries. To make a custom event pass through shadow DOM boundaries, set the composed flag to true when you create the event:
+
+
+**Composed path**
+
+```js
+constructor() {
+ this.super();
+ this.addEventListener('my-event', (e) => { console.log(e.composedPath())});
+}
+render() {
+ return html``;
+}
+doThing() {
+ let myEvent = new CustomEvent('my-event', { bubbles: true, composed: true });
+ this.dispatchEvent(myEvent);
+}
+```
+
+## Add an event listener to anything else
+
+When you're adding an event listener to the host element or its children, you don't need to worry about memory leaks. The memory allocated to the event listener will be destroyed when the host element is destroyed.
+
+However, when adding an event listener to something other than the host element or its children, you should add the listener in `connectedCallback` and remove it in `disconnectedCallback`:
+
+```js
+connectedCallback() {
+ super.connectedCallback();
+ window.addEventListener('hashchange', this.hashChangeListener);
+}
+
+disconnectedCallback() {
+ super.disconnectedCallback();
+ window.removeEventListener('hashchange', this.hashChangeListener);
+}
+```
+
+###
+
+Scenario 1
+
+MyElement constructor is called; ChildThing constructor is called; event listener is added to ChildThing
+Stuff happens, event listener fires, memory is allocated in its scope
+MyElement is destroyed; ChildThing is destroyed, and with it, the scope of the event listener; memory is freed up, all is well
+Scenario 2
+
+MyElement constructor is called; event listener is added to Window
+Stuff happens, event listener fires, memory is allocated in its scope
+MyElement is destroyed
+In Scenario 2, I am not sure when or how the memory in the scope created by the event listener on Window would get released. My understanding is that garbage collection works differently in different browsers and this scenario might not be good for memory management.
+
+Scenario 2.A
+
+MyElement's connectedCallback fires, event listener is added to Window
+Stuff happens, event listener fires, memory is allocated in its scope
+disconnectedCallback fires, event listener is removed from Window, memory is freed up and all is well
+The recommendation to use disconnectedCallback to remove event listeners added to things that aren't MyElement or its children seems clear in this scenario. As for why you would add it in connectedCallback instead of the constructor in this scenario, I can't say for sure, but it does seem nice and clean to do stuff in connectedCallback if you're going to undo it in disconnectedCallback. Maybe a scenario like the following would make it more relevant:
+
+Scenario 3
+
+MyElement is appended to ParentThing, MyElement's connectedCallback fires, event listener is added to ParentThing
+Stuff happens, event listener fires, memory is allocated in its scope
+MyElement is moved to a new position in DOM, disconnectedCallback fires, event listener is removed from ParentThing
+MyElement is appended to OtherThing, connectedCallback fires again, etc
+
+
+### A heading3
+
+```js
+some code
+```
+
+Something:
+
+* A list item
+* A list item
+
+## Heading 2
+
+```js
+code
+```
+
+```js
+code
+```
+
+
+**Example: Add an event listener to a child element**
+
+```js
+{% include projects/events/events/my-element.js %}
+```
+
+{% include project.html folder="events/events" openFile="my-element.js" %}
+
+## Add an event listener to some other DOM element
+
+
+
+
+## Best practices
+
+From which method should you add an event listener?
+
+* Add your event listener before the event can occur.
+* You can
+* You must add your
+
+### How can I ensure that the memory allocated to the event listener is cleaned up?
+
+
+A custom element can add an event listener to itself or its own children from its constructor without any issues
+
+Adding the listener in the constructor ensures that you will catch events that could possibly occur before the custom element has been added to DOM
+If the custom element adds an event listener to anything except itself or its children (e.g. window), you should add the listener in connectedCallback and remove it in disconnectedCallback
+
+
+
+
+
+
+{:.alert .alert-warning}
+
+ `;
+ }
+}
+
+customElements.define('my-element', MyElement);
From 67092d3ccdae32fc1543f348301c3642c5c91a7a Mon Sep 17 00:00:00 2001
From: Kate Jeffreys
Date: Thu, 3 Jan 2019 13:24:27 -0800
Subject: [PATCH 2/3] Flesh out events docs
---
docs/_guide/events.md | 202 +++++-------------
.../projects/events/child/index.html | 17 ++
docs/_includes/projects/events/child/index.ts | 1 +
.../projects/events/child/manifest.json | 14 ++
.../projects/events/child/my-element.js | 14 ++
.../events/childimperative/index.html | 17 ++
.../projects/events/childimperative/index.ts | 1 +
.../events/childimperative/manifest.json | 14 ++
.../events/childimperative/my-element.js | 19 ++
.../_includes/projects/events/host/index.html | 17 ++
docs/_includes/projects/events/host/index.ts | 1 +
.../projects/events/host/manifest.json | 14 ++
.../projects/events/host/my-element.js | 17 ++
13 files changed, 202 insertions(+), 146 deletions(-)
create mode 100644 docs/_includes/projects/events/child/index.html
create mode 100644 docs/_includes/projects/events/child/index.ts
create mode 100644 docs/_includes/projects/events/child/manifest.json
create mode 100644 docs/_includes/projects/events/child/my-element.js
create mode 100644 docs/_includes/projects/events/childimperative/index.html
create mode 100644 docs/_includes/projects/events/childimperative/index.ts
create mode 100644 docs/_includes/projects/events/childimperative/manifest.json
create mode 100644 docs/_includes/projects/events/childimperative/my-element.js
create mode 100644 docs/_includes/projects/events/host/index.html
create mode 100644 docs/_includes/projects/events/host/index.ts
create mode 100644 docs/_includes/projects/events/host/manifest.json
create mode 100644 docs/_includes/projects/events/host/my-element.js
diff --git a/docs/_guide/events.md b/docs/_guide/events.md
index e9f3b648..ffd7c6a1 100644
--- a/docs/_guide/events.md
+++ b/docs/_guide/events.md
@@ -22,40 +22,12 @@ TODO: Tidy up this page
You can use the `firstUpdated` callback to add an event listener after the element has first been rendered:
```js
-class MyElement extends LitElement {
- firstUpdated(changedProperties) {
- this.addEventListener('click', (e) => { ... });
-})
+{% include projects/events/host/my-element.js %}
```
-```js
-class MyElement extends LitElement {
- firstUpdated(changedProperties) {
- this.addEventListener('click', this.clickHandler);
- }
- clickHandler(e) { ... }
-)
-```
+{% include project.html folder="events/host" openFile="my-element.js" %}
-If your event might occur before the element has finished rendering, you can add the listener from the constructor:
-
-```js
-class MyElement extends LitElement {
- constructor() {
- super.constructor();
- this.addEventListener('some-event', (e) => { ... });
-})
-```
-
-```js
-class MyElement extends LitElement {
- constructor() {
- super.constructor();
- this.addEventListener('some-event', this.someEventHandler);
- }
- someEventHandler(e) { ... }
-)
-```
+If your event might occur before the element has finished rendering, you can add the listener from the constructor.
## Add an event listener to the child element of a LitElement host
@@ -64,14 +36,11 @@ class MyElement extends LitElement {
You can add an event listener to an element's DOM child using lit-html data binding syntax:
```js
-render() {
- return html``;
-}
-handleClick(e) {
- // ...
-}
+{% include projects/events/child/my-element.js %}
```
+{% include project.html folder="events/child" openFile="my-element.js" %}
+
See the documentation on [Templates](templates) for more information on lit-html template syntax.
**Option 2: Add the listener imperatively**
@@ -79,21 +48,59 @@ See the documentation on [Templates](templates) for more information on lit-html
To add an event listener to a child element imperatively, you must do so in or after `firstUpdated` to ensure that the child element exists. For example:
```js
-render() {
- return html``;
-}
+{% include projects/events/childimperative/my-element.js %}
+```
+
+{% include project.html folder="events/childimperative" openFile="my-element.js" %}
-firstUpdated(changedProperties) {
- let el = this.shadowRoot.getElementById('mybutton');
- el.addEventListener('click', this.handleClick);
+## Add an event listener to anything else
+
+When you're adding an event listener to the host element or its children, you don't need to worry about memory leaks. The memory allocated to the event listener will be destroyed when the host element is destroyed.
+
+However, when adding an event listener to something other than the host element or its children, you should add the listener in `connectedCallback` and remove it in `disconnectedCallback`:
+
+```js
+connectedCallback() {
+ super.connectedCallback();
+ window.addEventListener('hashchange', this.hashChangeListener);
}
-...
-handleClick(e) {
- ...
+
+disconnectedCallback() {
+ super.disconnectedCallback();
+ window.removeEventListener('hashchange', this.hashChangeListener);
}
```
-### Bubbling, custom events, composed path, etc
+### Why
+
+Because garbage collection.
+
+**Bad**
+
+1. MyElement creates an event listener on Window
+2. Event listener fires, memory is allocated in its scope
+3. MyElement is destroyed
+
+However, the memory allocated to the event listener is still in use. To avoid this:
+
+**Good**
+
+1. MyElement adds event listener to Window
+2. Event listener fires, memory is allocated in its scope
+3. MyElement's disconnectedCallback fires, event listener is removed from Window
+
+Memory is freed up and all is well.
+
+**Also Good**
+
+If the element can move around the DOM during its lifecycle, you may need to add the event listener in `connectedCallback`:
+
+1. MyElement is appended to ParentElement, MyElement's connectedCallback fires, event listener is added to ParentElement
+2. Event listener fires, memory is allocated in its scope
+3. MyElement is moved to a new position in DOM, disconnectedCallback fires, event listener is removed from ParentElement, memory is freed
+4. MyElement is appended to OtherElement, connectedCallback fires again, etc
+
+## Bubbling, custom events, composed path, etc
**Event bubbling**
@@ -153,104 +160,6 @@ doThing() {
}
```
-## Add an event listener to anything else
-
-When you're adding an event listener to the host element or its children, you don't need to worry about memory leaks. The memory allocated to the event listener will be destroyed when the host element is destroyed.
-
-However, when adding an event listener to something other than the host element or its children, you should add the listener in `connectedCallback` and remove it in `disconnectedCallback`:
-
-```js
-connectedCallback() {
- super.connectedCallback();
- window.addEventListener('hashchange', this.hashChangeListener);
-}
-
-disconnectedCallback() {
- super.disconnectedCallback();
- window.removeEventListener('hashchange', this.hashChangeListener);
-}
-```
-
-###
-
-Scenario 1
-
-MyElement constructor is called; ChildThing constructor is called; event listener is added to ChildThing
-Stuff happens, event listener fires, memory is allocated in its scope
-MyElement is destroyed; ChildThing is destroyed, and with it, the scope of the event listener; memory is freed up, all is well
-Scenario 2
-
-MyElement constructor is called; event listener is added to Window
-Stuff happens, event listener fires, memory is allocated in its scope
-MyElement is destroyed
-In Scenario 2, I am not sure when or how the memory in the scope created by the event listener on Window would get released. My understanding is that garbage collection works differently in different browsers and this scenario might not be good for memory management.
-
-Scenario 2.A
-
-MyElement's connectedCallback fires, event listener is added to Window
-Stuff happens, event listener fires, memory is allocated in its scope
-disconnectedCallback fires, event listener is removed from Window, memory is freed up and all is well
-The recommendation to use disconnectedCallback to remove event listeners added to things that aren't MyElement or its children seems clear in this scenario. As for why you would add it in connectedCallback instead of the constructor in this scenario, I can't say for sure, but it does seem nice and clean to do stuff in connectedCallback if you're going to undo it in disconnectedCallback. Maybe a scenario like the following would make it more relevant:
-
-Scenario 3
-
-MyElement is appended to ParentThing, MyElement's connectedCallback fires, event listener is added to ParentThing
-Stuff happens, event listener fires, memory is allocated in its scope
-MyElement is moved to a new position in DOM, disconnectedCallback fires, event listener is removed from ParentThing
-MyElement is appended to OtherThing, connectedCallback fires again, etc
-
-
-### A heading3
-
-```js
-some code
-```
-
-Something:
-
-* A list item
-* A list item
-
-## Heading 2
-
-```js
-code
-```
-
-```js
-code
-```
-
-
-**Example: Add an event listener to a child element**
-
-```js
-{% include projects/events/events/my-element.js %}
-```
-
-{% include project.html folder="events/events" openFile="my-element.js" %}
-
-## Add an event listener to some other DOM element
-
-
-
-
-## Best practices
-
-From which method should you add an event listener?
-
-* Add your event listener before the event can occur.
-* You can
-* You must add your
-
-### How can I ensure that the memory allocated to the event listener is cleaned up?
-
-
-A custom element can add an event listener to itself or its own children from its constructor without any issues
-
-Adding the listener in the constructor ensures that you will catch events that could possibly occur before the custom element has been added to DOM
-If the custom element adds an event listener to anything except itself or its children (e.g. window), you should add the listener in connectedCallback and remove it in disconnectedCallback
-
@@ -278,4 +187,5 @@ Something.
**Remember to something.** Something something.
-
\ No newline at end of file
+
+
diff --git a/docs/_includes/projects/events/child/index.html b/docs/_includes/projects/events/child/index.html
new file mode 100644
index 00000000..205b902b
--- /dev/null
+++ b/docs/_includes/projects/events/child/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ lit-element code sample
+
+
+
+
+
+
+
+
diff --git a/docs/_includes/projects/events/child/index.ts b/docs/_includes/projects/events/child/index.ts
new file mode 100644
index 00000000..735d0c5f
--- /dev/null
+++ b/docs/_includes/projects/events/child/index.ts
@@ -0,0 +1 @@
+import './my-element.js';
diff --git a/docs/_includes/projects/events/child/manifest.json b/docs/_includes/projects/events/child/manifest.json
new file mode 100644
index 00000000..759a8a50
--- /dev/null
+++ b/docs/_includes/projects/events/child/manifest.json
@@ -0,0 +1,14 @@
+{
+ "title": "lit-element code sample",
+ "description": "lit-element code sample",
+ "files": [
+ "my-element.js",
+ "index.html",
+ "index.ts"
+ ],
+ "dependencies": {
+ "@polymer/lit-element": "latest",
+ "@webcomponents/webcomponentsjs": "latest"
+ },
+ "template": "typescript"
+}
diff --git a/docs/_includes/projects/events/child/my-element.js b/docs/_includes/projects/events/child/my-element.js
new file mode 100644
index 00000000..66893134
--- /dev/null
+++ b/docs/_includes/projects/events/child/my-element.js
@@ -0,0 +1,14 @@
+import { LitElement, html } from '@polymer/lit-element';
+
+class MyElement extends LitElement {
+ render() {
+ return html`
+
+ `;
+ }
+ doThing(e) {
+ console.log(e);
+ }
+}
+
+customElements.define('my-element', MyElement);
diff --git a/docs/_includes/projects/events/childimperative/index.html b/docs/_includes/projects/events/childimperative/index.html
new file mode 100644
index 00000000..205b902b
--- /dev/null
+++ b/docs/_includes/projects/events/childimperative/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ lit-element code sample
+
+
+
+
+
+
+
+
diff --git a/docs/_includes/projects/events/childimperative/index.ts b/docs/_includes/projects/events/childimperative/index.ts
new file mode 100644
index 00000000..735d0c5f
--- /dev/null
+++ b/docs/_includes/projects/events/childimperative/index.ts
@@ -0,0 +1 @@
+import './my-element.js';
diff --git a/docs/_includes/projects/events/childimperative/manifest.json b/docs/_includes/projects/events/childimperative/manifest.json
new file mode 100644
index 00000000..759a8a50
--- /dev/null
+++ b/docs/_includes/projects/events/childimperative/manifest.json
@@ -0,0 +1,14 @@
+{
+ "title": "lit-element code sample",
+ "description": "lit-element code sample",
+ "files": [
+ "my-element.js",
+ "index.html",
+ "index.ts"
+ ],
+ "dependencies": {
+ "@polymer/lit-element": "latest",
+ "@webcomponents/webcomponentsjs": "latest"
+ },
+ "template": "typescript"
+}
diff --git a/docs/_includes/projects/events/childimperative/my-element.js b/docs/_includes/projects/events/childimperative/my-element.js
new file mode 100644
index 00000000..3fe4d293
--- /dev/null
+++ b/docs/_includes/projects/events/childimperative/my-element.js
@@ -0,0 +1,19 @@
+import { LitElement, html } from '@polymer/lit-element';
+
+class MyElement extends LitElement {
+
+ firstUpdated() {
+ let button = this.shadowRoot.getElementById('mybutton');
+ button.addEventListener('click', this.doThing);
+ }
+ render() {
+ return html`
+
+ `;
+ }
+ doThing(e) {
+ console.log(e);
+ }
+}
+
+customElements.define('my-element', MyElement);
diff --git a/docs/_includes/projects/events/host/index.html b/docs/_includes/projects/events/host/index.html
new file mode 100644
index 00000000..205b902b
--- /dev/null
+++ b/docs/_includes/projects/events/host/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ lit-element code sample
+
+
+
+
+
+
+
+
diff --git a/docs/_includes/projects/events/host/index.ts b/docs/_includes/projects/events/host/index.ts
new file mode 100644
index 00000000..735d0c5f
--- /dev/null
+++ b/docs/_includes/projects/events/host/index.ts
@@ -0,0 +1 @@
+import './my-element.js';
diff --git a/docs/_includes/projects/events/host/manifest.json b/docs/_includes/projects/events/host/manifest.json
new file mode 100644
index 00000000..759a8a50
--- /dev/null
+++ b/docs/_includes/projects/events/host/manifest.json
@@ -0,0 +1,14 @@
+{
+ "title": "lit-element code sample",
+ "description": "lit-element code sample",
+ "files": [
+ "my-element.js",
+ "index.html",
+ "index.ts"
+ ],
+ "dependencies": {
+ "@polymer/lit-element": "latest",
+ "@webcomponents/webcomponentsjs": "latest"
+ },
+ "template": "typescript"
+}
diff --git a/docs/_includes/projects/events/host/my-element.js b/docs/_includes/projects/events/host/my-element.js
new file mode 100644
index 00000000..026c8203
--- /dev/null
+++ b/docs/_includes/projects/events/host/my-element.js
@@ -0,0 +1,17 @@
+import { LitElement, html } from '@polymer/lit-element';
+
+class MyElement extends LitElement {
+ firstUpdated() {
+ this.addEventListener('click', this.clickHandler);
+ }
+ clickHandler(e) {
+ console.log(e.target);
+ }
+ render() {
+ return html`
+
Click me
+ `;
+ }
+}
+
+customElements.define('my-element', MyElement);
From 9b1c13a0bd9e8b83286599a46bbd831cd66b2939 Mon Sep 17 00:00:00 2001
From: Kate Jeffreys
Date: Mon, 4 Feb 2019 15:03:30 -0800
Subject: [PATCH 3/3] Heavy edits to events docs
---
docs/_guide/events.md | 262 +++++++++++++++++++++++-------------------
1 file changed, 145 insertions(+), 117 deletions(-)
diff --git a/docs/_guide/events.md b/docs/_guide/events.md
index ffd7c6a1..2df398d5 100644
--- a/docs/_guide/events.md
+++ b/docs/_guide/events.md
@@ -4,188 +4,216 @@ title: Events
slug: events
---
-TODO: Tidy up this page
-
{::options toc_levels="1..3" /}
* ToC
{:toc}
## Overview
-* Default event context is `this` - no need for `this.handlerMethod.bind(this)`
-* You can use `this` referring to the host inside an event handler
-* Add event listeners in a method that is guaranteed to fire before the event occurs
-* For optimal loading performance, add your event listener as late as possible
-
-## Add an event listener to a LitElement host
+### Where to add your event listeners
-You can use the `firstUpdated` callback to add an event listener after the element has first been rendered:
+You need to add event listeners in a method that is guaranteed to fire before the event occurs. However, for optimal loading performance, you should add your event listener as late as possible.
-```js
-{% include projects/events/host/my-element.js %}
-```
+You can add event listeners:
-{% include project.html folder="events/host" openFile="my-element.js" %}
+* **Via your component's template.**
-If your event might occur before the element has finished rendering, you can add the listener from the constructor.
+ You can use lit-html `@event` bindings in your template inside the `render` function to add event listeners to your component.
-## Add an event listener to the child element of a LitElement host
+ **Example**
-**Option 1: Use lit-html template syntax**
-
-You can add an event listener to an element's DOM child using lit-html data binding syntax:
-
-```js
-{% include projects/events/child/my-element.js %}
-```
+ ```js
+ render() {
+ return html`