Solution 1 :

Your code is confusing the calling of a function and referencing a function for an event handler. For example, on this line:

select_1.onchange = myChoices([tipo_via], '/numero_via', select_2);

…what this means is to call myChoices with some arguments and assign the return value to onchange. Instead, what you want is for when the onchange event occurs, you want to call myChoices with those arguments. This is more of what you want:

select_1.addEventListener(
  'change', 
  () => myChoices([tipo_via], '/numero_via', select_2));
select_2.addEventListener(
  'change',
  () => myChoices([tipo_via, numero_via], '/apendice_v', select_3));

I changed assignment to onchange to the preferred addEventListener, but the most important key here is wrapping the calling of your function in a new function so the actual call isn’t made right away. Now, it’s not until the DOM change event is fired that the arrow function will be called, and within that function you’ll have the call to myChoices(...). Notice that the original working code also was referencing a listener function to defer the call until the event occurred.

Solution 2 :

The DOM may not be ready (HTML fully parsed and DOM tree constructed internally), so you have to execute your code in a DOMContentLoaded event.

If that doesn’t solve the problem then post a detailed error description, e.g. errors from the browser console.

Problem :

I have placed the following script at the very end of the body section of my html file where select_1, select_2, select_3 are dynamic (dependent) drop-down lists. (Let’s call the script below NEW SCRIPT).

function json(response) {
    return response.json()
}

function url_parser(XArray, some_str){
    var url_str = [];
    for (var i=0; i < XArray.length; ++i)
        url_str.push('/'+XArray[i].value);
    url_str.push(some_str);
    url_str = url_str.join('');
    return url_str
}

function selectionHTML(nextFormElement, data){
    let optionHTML = '';
        for (let tmp of data.select_array) {
            optionHTML += '<option value="' + tmp.gid + '">' + tmp.gid + '</option>';
        }
        nextFormElement.innerHTML = optionHTML;
}


function myChoices(XArray, some_str, nextFormElement){
    my_url = url_parser(XArray, some_str);
    fetch(my_url).then(json).then(selectionHTML.bind(null, nextFormElement));
}


let select_1 = document.getElementById('tipo_via');
let select_2 = document.getElementById('numero_via');
let select_3 = document.getElementById('apendice_via');

select_1.onchange = myChoices([tipo_via], '/numero_via', select_2);
select_2.onchange = myChoices([tipo_via, numero_via], '/apendice_v', select_3);

However, this script does not work. The only way it work is to:

  1. remove it from the html file and
  2. execute it in the console in a certain order

Providing details in the order of execution:

  1. Execute (in console) all code between function json(response) and let select_3 = document.getElementById('apendice_via');
  2. change the value (in the page) of select_1.
  3. Execute (in console) select_1.onchange = myChoices([tipo_via], '/numero_via', select_2); (select_2 now correctly updates).
  4. change the value (in the page) of select_2.
  5. Execute (in console) select_2.onchange = myChoices([tipo_via, numero_via], '/apendice_v', select_3); (select_3 now correctly updates).

After looking at similar problems, I thought the problem was (maybe still is) related to the timing of the page loading which is why I placed the script at the end of <body>. I have also tried by placing it in the <head>

The NEW SCRIPT was meant to replace the OLD SCRIPT (below … which works perfectly) as there will be 8 drop-down lists in total.

function json(response) {
    return response.json()
}

function url_parser(XArray, some_str,){
    var url_str = [];
    for (var i=0; i < XArray.length; ++i)
        url_str.push('/'+XArray[i].value);
    url_str.push(some_str);
    url_str = url_str.join('');
    return url_str
}


let select_1 = document.getElementById('tipo_via');
let select_2 = document.getElementById('numero_via');
let select_3 = document.getElementById('apendice_via');


select_1.onchange = function(){
    my_url = url_parser([tipo_via], '/numero_via');
    fetch(my_url).then(json).then(function(data) {
            let optionHTML = '';
            for (let tmp of data.select_array) {
                optionHTML += '<option value="' + tmp.gid + '">' + tmp.gid + '</option>';
            }
            select_2.innerHTML = optionHTML;
        });
}

select_2.onchange = function(){
    my_url = url_parser([tipo_via, numero_via], '/apendice_v');
    fetch(my_url).then(json).then(function(data) {
            let optionHTML = '';
            for (let tmp of data.select_array) {
                optionHTML += '<option value="' + tmp.gid + '">' + tmp.gid + '</option>';
            }
            select_3.innerHTML = optionHTML;
        });
}

What I can’t get my head around is if the problem is really related to page loading, why does it affect the NEW script and not the OLD one.

Any help will be greatly appreciated. Thanks in advance.

Comments

Comment posted by mr. pc_coder

what is [tipo_via] ?

Comment posted by David

In what way is it “not working”? Are there any errors on the browser’s development console? When you use the browser’s script debugger to step through the code as it executes, which operation is the first to fail?

Comment posted by JavaScript

Never touch a running system.

Comment posted by montoisky

Hi Jacob. Thank you so much. That’s done the job. Less spaghetti code for me thanks to you.

By

Leave a Reply

Your email address will not be published. Required fields are marked *