Youtube channel !

Be sure to visit my youtube channel

Friday, December 06, 2019

Event delegation in JavaScript

In JavaScript we use event delegation for two main reasons:
1) to be able to process events coming from dynamically added page elements.
2) to achieve better application performance by listening to only one main element instead of having to add and remove event listeners each time a new element is dynamically added to the DOM.
More intriguing JavaScript aspects you can discover inside the JavaScript for beginners - learn by doing course.

 


In case of event delegation, when event occurs, we can filter out on which of the event generated source elements we would like to respond to using the event's target property: event.target
Here are two examples on how to use the event target:
// to filter out the processing of events coming from elements having different classes:
if (!event.target.classList.contains('my_class')) return;
// or to do filtering based on particular tag:
if (event.target.tagName == 'INPUT') {
// do our processing only if the source event came from an input tag
}

Example: Here we create an html with a simple ul/li list and add new LI button:
<button id="add">Add new LI</button>
<ul class="characters">
    <li>
        <input type="checkbox" data-index="0" id="child0">
        <label for="child0">Child 0</label>
    </li>
    <li>
        <input type="checkbox" data-index="1" id="child1">
        <label for="child1">Child 1</label>
    </li>
    <li>
        <input type="checkbox" data-index="2" id="child2">
        <label for="child2">Child 2 </label>
    </li>
</ul>
<script src="event_delegate.js"></script>

And here is our JavaScript code which adds new LI elements dynamically:
document.querySelector('#add').addEventListener('click', () => {
 // we create a new li element
let li = document.createElement('li');
// we get the last data-index attribute withing ul>li
    let dataId = characterList
        .lastElementChild // we use ElementChild instead of Child, because it ignores text and comment nodes
        .firstElementChild
        .getAttribute('data-index');
// increase the last id with 1
    ++dataId;
// construct the ne LI element with increased dataId
    li.innerHTML = `
    <input
    type="checkbox"
    data-index="${dataId}"
    id="child${dataId}">
    <label for="child${dataId}">Child ${dataId}</label>
    `;
// append the new LI eleemnt to the UL
    characterList.append(li);
});

// this is our little debug function showing up the event and where it is coming from
function toggle(event) {
    console.log('event: ' + event); //the event
    console.log('target: ' + event.target); //where occured the event
    console.log('currentTarget: ' + event.currentTarget); //attached parent element
    console.log('toggled element with id: ' + event.target.id);
}

// the actual parent element, where the event delegation is happening
const characterList = document.querySelector('.characters');
// here, instead of having multiple LI attached event listeners, we just attach 1 event listener to the UL list
characterList.addEventListener('click', toggle);

// Bonus: here is how to query specific element using its data-index attribute:
console.log(document.querySelector('input[data-index="1"]'));

Congratulations!

Resources:

JavaScript for beginners - learn by doing

Tuesday, November 26, 2019

One way data binding in JavaScript

Alright, since two-way data binding is often used in Angular, React and Vue and at the same time, not everyone likes it. I think that simple one-way data binding when writing JavaScript code is actually beneficial. More intriguing JavaScript aspects you can discover inside the JavaScript for beginners - learn by doing course.


What is one-way data binding: simply-said we would like the moment we change our data variable (model) this change to reflect immediately inside our generated HTML. Let's take a look at this example:
We have two span elements with two data bindings quote1 and quote2. You may consider them as just ids:
<span data-binding="quote1"></span>
<br>
<span data-binding="quote2"> </span>

Then we create the HTML change function (render) that will grab the element that is passed as a "property" parameter and will change its innerHTML based on what is inside the same property, taken from a special state object. This way effectively changing the HTML based on a passed parameter.

const render = property => {
document.querySelector(`[data-binding="${property}"]`).innerHTML = state.property;
};

Now to the main function setState. Its goal is to create a Proxy around a passed state obect, and whenever property of an object inside this state changes (i.e. user puts information inside (set)), the proxy will perform certain things, such as: setting the updated value inside the property, as well as using the previously defined render function to update the HTML view):

const setState = state => {
return new Proxy(state, {
set(target, property, value) { // detect if there are changes inside the property of a certain object
target.property = value; // updates the value of the property
render(property); // renders the HTML with the updated property to the screen
}
});
};

Now lets set an initial state:
const state = setState({
quote1: 'Initial quote state.'
});

Once it is set we can display the initial state on the console: console.log(state.quote1);

We can now try to modify some properties inside the Proxy state:
state.quote1 = 'quote1 new state';
state.quote2 = 'quote2 new state';
and see how their updated changes are reflected on the browser HTML.

You now may use the Proxy design pattern for your projects. 

Congratulations!

Resources:

JavaScript for beginners - learn by doing

Subscribe To My Channel for updates

Things to do after install Fedora 43

#!/bin/bash # 1. SETUP REPOSITORIES echo ">>> Setting up Repositories (RPM Fusion, Copr, Cisco)..." # Install RPM Fusion ...