After rendering the component, the next thing we need to do is add event listeners. After all, all interactions begin with event listeners.
Normally, we need to add event listeners after we get the element from the DOM.
const element = document.querySelector('some-element')
element.addEventListener('eventName', event => {
// Do something
})
Unfortunately, Tiny users won’t be able to add event listeners this way. Why? Because they can’t grab the element from the DOM before the component gets rendered.
So we need to create a way for users to add event listeners directly onto elements inside Tiny.
Adding Event Listeners to HTML Elements
There’s a way to add event listeners directly on HTML elements. It uses the following syntax:
<button onevent="callback">Click me</button>
function callback (event) {
// Do something
}
onevent is an on keyword followed by the name of the event you want to listen to. For example, you can use onclick to listen to clicks.
callback is the event handler. If you use a function name, this name has to be accessible in the global scope.
This method is rarely used since it requires variables in the global scope – which is a bad practice.
But we can use this syntax to create event listeners inside each Tiny component. In fact, most frameworks actually do something like this.
For example, you can use onClick in a React component.
<button onClick={handleClick}>Click me</button>
Vue does it slightly differently with a v-on: prefix.
We can do something similar to React and Vue. The problem with copying their style is we need to parse the HTML to get the event name. However, parsing HTML is a challenging task.
The simplest alternative I found is to use a custom data attribute. The downside to using custom data attributes is everything gets converted into strings. But we can live with this problem because we’re building a framework more for educational purposes and not for real-use. I don’t want you to get stuck with parsing HTML. I want you to understand the inner workings of what’s actually going on.
We’ll use a custom data-attribute called tiny-listener. In tiny-listener, we need to tell Tiny two things:
We want to allow users to create an event handler directly inside the Tiny call. Each event handler is a method. In this case, we have two methods: increaseCount and increaseChildCount
We want to add event listeners after the component gets rendered. Let’s start by creating a function called _addEventListeners and call it after _render.
export default function Tiny (options) {
// ...
function _addEventListeners () {
// ...
}
_render()
_addEventListeners()
}
To add event listeners, we need to find all elements that contain the tiny-listener attribute. Each element with this attribute has at least one event listener (but we’re only dealing with one at this point).
export default function Tiny (options) {
// ...
function _addEventListeners () {
const listenerElements = document.querySelectorAll('[tiny-listener]')
for (const listenerElement of listenerElements) {
console.log(listenerElement)
}
}
// ...
}
We can find the attribute from each element with getAttribute.
export default function Tiny (options) {
// ...
function _addEventListeners () {
const listenerElements = document.querySelectorAll('[tiny-listener]')
for (const listenerElement of listenerElements) {
const attribute = listenerElement.getAttribute('tiny-listener')
console.log(attribute)
}
}
// ...
}
attribute is a string. We need to extract the event name (click) and the callback (increaseCount or increaseChildCount) into variables so we can use them.