JavaScript Event Delegation

After completing the third Flatiron phase utilizing Rails, JavaScript’s fluidity and lack of required structure was somewhat stressful. Initially, I had plans to create a much larger project with some more in-depth functionality. The backend was created using Rails API and SQLite3. I initially attempted to use Postgres for the first time but ran into some issues, so I reverted back to the previous.

I created the bones for an application I would like to continue building, called Single Track. The application is geared towards an shop owner tracking of ongoing customers within a parent class of stores. I originally wanted to add functionality to also create and keep track of each item which each customer purchased but will implement this, at a later date.

During development of my application, I used multiple AJAX calls, including GET, POST, and DELETE. One problem I ran into several times was the static nature of .querySelector and .querySelectorAll.

During the initial fetch for my stores index(the Rails parent-class), I would get back the JSON data from my Rails API containing all of the stores and their associated customers. I would then add a delete button to each div along with all of my associated store data.

const deleteButtons = document.querySelectorAll('.delete-store)

I could use .querySelectorAll to grab all of the buttons with the desired class and then add an eventListener to each one, which worked just fine. The problem with this method was during the post fetch for a new Store.

Using the original variable I set to grab all of the delete buttons with the desired class was not a dynamic list which could be added to easily. Therefore, my newly created Store with it’s delete button hadn’t yet been added to the list of buttons with the delete addEventListener.

I was able to get around this issue with Event Delegation. During Event Delegation, the event listener is not just being added to a single (or static list) of object.

document.addEventListener('click', function(event) {if (event.target.matches('.delete-store')) {const store = Store.findById(event.target.id)const url = `http://localhost:3000/api/stores/${event.target.id}`deleteStore(url, store)}}, false);

Instead of specifically targeting buttons I knew to be there and then, when I created new instances, ensuring that I followed up and also added their buttons to the list of eventListeners, I used this Event Delegation method. It would search through the DOM, searching for anything that included the desired class. This meant it worked for both things pulled from the database during initial load as well as things created dynamically through the front end. This process also removed a lot of spurious and not DRY code.