Repopulate to Select Option

Viewed 85

i would like to repopulate data to select option but i only have one select data and other select are not work, i think their are dependent on "change" function. Please ...

first i create state and region drop down with json data, then set change method on this select and get district data and populate those data at district select, then set change method on district select and get data for township and populate at township select.

onclick function set on btn_save and populate all data to table.

Here were my problem come out. i want to edit my data and i set edit button on table then i want to populate table data to previous select. but it's only work in state region select,

This is my simple html code

     <div>
        <select name="state" id="state">
            <option value="">State And Region</option>
        </select>        
        <select name="district" id="district">
            <option value="">District</option>
        </select>
        <select name="township" id="township">
            <option value="">Township</option>
        </select>
        <input type="text" id="desc" placeholder="Enter your keyword"> 
        <button id="btn_save">Save</button>
    </div>
    <div>
        <table class="tbl_desc">
            <tr>
                <th>State</th>
                <th>District</th>
                <th>Township</th>
                <th>Description</th>
                <th>Action</th>
            </tr>
        </table>
    </div>

This is my js code

fetch('/data/lp_state_region.json')
.then( response => {
    return response.json()
})
.then(json => {
    $('#state').append(json.map( sr => {
        return `<option value=${sr.sr_code}>${sr.sr_name}</option>` ;
    }));
});

$('#state').change( e => {
    let sr_code = e.target.value ;
    fetch('/data/lp_district.json')
    .then( res => {
        return res.json();
    })
    .then( json => {
        $('#district').html('');
        $('#district').html(`<option value=''>District</option>`);
        $('#district').append(json.map(d => {
            if(sr_code == d.sr_code){
                return `<option value=${d.d_code}>${d.d_name}</option>` ;
            }
        }));
    });
});

$('#district').change( e => {
    let d_code = e.target.value ;
    fetch('/data/lp_township.json')
    .then( res => {
        return res.json();
    })
    .then( json => {
        $('#township').html('');
        $('#township').html(`<option value=''>Township</option>`);
        $('#township').append( json.map( ts => {
            if(ts.d_code == d_code){
                return `<option value=${ts.ts_code}>${ts.ts_name}</option>` ;
            }
        }));
    });
});

$('#btn_save').click(() => {
    let tr = "<tr>" ;
    tr += `<td class="state">${$('#state').val()}</td>` ;
    tr += `<td class="district">${$('#district').val()}</td>` ;
    tr += `<td class="township">${$('#township').val()}</td>` ;
    tr += `<td class="desc">${$('#desc').val()}</td>` ;
    tr += "<td><button onclick='rePopulateSelect(this);'>Edit</button></td>" ;
    tr += "</tr>" ;
    $(".tbl_desc").append(tr);

    $('#state').val('').change();
    $('#district').val('').change();
    $('#township').val('').change();
    $('#desc').val('');
});

function rePopulateSelect(btn){
    let tr = $(btn).closest('tr');
    let state = tr.find('.state').html() ;
    let district = tr.find('.district').html();
    let township = tr.find('.township').html();
    let desc = tr.find('.desc').html();
    
    // i want to repopulate this data to select
    // i am stuck at here
    $('#state').val(state).change();
    $('#district').val(district).change();
    $('#township').val(township).change();
    $('#desc').val(desc);
}


2 Answers

The reason is you are using fetch without waiting for the promise to fulfill.

When you make your calls at the end of rePopulateSelect:

    $('#state').val(state).change();
    $('#district').val(district).change();
    $('#township').val(township).change();
    $('#desc').val(desc);
}

you are making some async-calls in your change-handler. To solve this, try to await in the change-handlers, e.g. in your state-change-handler:

// create function for initing districts
async function InitDistricts(selectedState) {
    await fetch('https://hoesein.github.io/select_error/data/lp_district.json')
    .then( res => {
        return res.json();
    })
    .then( json => {
        $('#district').html('');
        $('#district').html(`<option value=''>District</option>`);
        $('#district').append(json.map(d => {
            if(selectedState == d.sr_code){
                return `<option value=${d.d_code}>${d.d_name}</option>` ;
            }
        }));
    });
}

// attach as eventhandler
$('#state').change((e) => InitDistricts(e.target.value));

async function InitTownships(selectedDistrict) {
...
}

also in your rePopulateSelect use the functions you created and use await only when it makes sense...

async function rePopulateSelect(btn) {

....

    $('#state').val(state);
    await InitDistricts(state);
    
    $('#district').val(district);
    await InitTownships(district);
    
    $('#township').val(township);
    $('#desc').val(desc);
}

Ok, seems that the problem is pretty obvious. You are changing the value of for example #district, that makes your #district select option to be set as selected. But as ajax is an async call, after that you are rewriting the code of the options so it doesn't contain any selected option.

You should append your selects in you ajax code with:

if(value = this_select_value) <option selected value="..."/>
else <option value="..."/>

And as this_select_value you should use some other select attribute than value (val()), as it's being rewritten when you clear the options with html(). Some virtual one, like attr('last_val',val);

(not a valid code, just to show the idea, could fix your code, but I can't edit it on github)

Related