I would like to change the execution order of my event listeners but they are interdependent

37 Views Asked by At

I am new to javascript and html coding. I am writing an html form with a javascript code in it which allows the user to add a list of venues and write information about them. When a venue is added by the user, he should specify, inter alia, its location, choosing in a <select> element bewteen "Urban", "Suburban", and "Mountainous" context.

Under the row of information about the venue, the user can add some origins and specify distances between the origins and the venue, by clicking on a button called "Add Origin and Distance".

What I am trying to do is to make a checkbox with label "Use of city buses" appear, next to each origin and destination (for each venue), ONLY when the "Suburban" context has been chosen by the user. See picture below :

enter image description here

The problem is that my event listener for the <select> venue location is inside the event listener of the "Add Origin and Distance" button. This because, in order to access the id of the <select> element, I need a "const" called venueNumber which is defined inside the "Add Origin and Distance" button listener. So basically, the "Use of city buses" checkbox only appears if we change the <select> option once we have clicked on the "Add Origin and Distance" button (and I would like it to appear even if the user first selects "Suburban", and then clicks the button).

Here is a simplified part of my html code :

function updateVenueFields() {

    venueContainer.innerHTML = '';

    for (let i = 1; i <= venueCount; i++) {
        const newVenueRow = document.createElement('div');
        newVenueRow.classList.add('venue-row');
        newVenueRow.innerHTML = `
            <label>Venue ${i}</label>

            <label for="venue_location_${i}">Location:</label>
            <select name="venue_location_${i}" id="venue_location_${i}" required>
                <option value="" disabled selected hidden>Specify venue location</option>
                <option value="urban">Urban context</option>
                <option value="suburban">Suburban context</option>
                <option value="mountainous">Mountainous context</option>
            </select>

            <div id="origin-distance-section-${i}">
                <p>If known, specify origin(s) and distance(s) for Venue ${i}:</p>
                <div id="origin-distance-container-${i}"></div>
                <button type="button" class="add-origin-distance-btn" data-venue="${i}">+ Add Origin and Distance</button>
            </div>
        `;

        venueContainer.appendChild(newVenueRow);

        const addOriginDistanceBtn = newVenueRow.querySelector('.add-origin-distance-btn');
        addOriginDistanceBtn.addEventListener('click', function() {
            
            const venueNumber = this.getAttribute('data-venue');
            const originDistanceContainer = document.getElementById(`origin-distance-container-${venueNumber}`);
            const originCounter = originDistanceContainer.children.length + 1;

            document.getElementById('venue_location_' + venueNumber).addEventListener('input', function() { 
                const select_value = document.getElementById('venue_location_' + venueNumber).value;
                if (select_value === 'suburban') {
                    document.getElementById('cityBusesInput ' + venueNumber + '-' + originCounter).classList.remove('hidden');
                } else {
                    document.getElementById('cityBusesInput ' + venueNumber + '-' + originCounter).classList.add('hidden');
                }
            });

            originDistanceContainer.classList.remove('hidden');

            addOriginAndDistance(originDistanceContainer, venueNumber, originCounter);

        });
    }
}

I tried moving the event listener of the venue location <select> element out of the other event listener so that it doesn't only fire when the button is clicked. However, I've had trouble getting the <select> element because of its changing id (depending on i). I tried using

document.querySelector('[id^="venue_location_"]').id

instead of

document.getElementById('venue_location_' + venueNumber)

in order not to use "venueNumber", but it didn't work. The result was that I couldn't add more than 1 venue and I couldn't add any origins and destinations.

0

There are 0 best solutions below