kate_hudson kate_hudson - 4 months ago 6
Javascript Question

Resetting select options based on choice

I have the following data set

array:4 [
"data" => array:2 [
2015 => array:2 [
"english" => array:1 [
"chips" => array:1 [
0 => "img1.png"
]
]
"french" => array:1 [
"mussles" => array:1 [
0 => "img1.png"
]
]
]
2016 => array:2 [
"indian" => array:1 [
"madras" => array:1 [
0 => "img1.png"
]
]
"italien" => array:1 [
"pasta" => array:1 [
0 => "img1.png"
]
]
]
]
]


To appropriately display the correct data I do the following

<select id="year" class="form-control">
@foreach($fileData["data"] as $year => $countries)
<option value="{{ $year }}">{{ $year }}</option>
@endforeach
</select>

<select id="country" class="form-control hide">
@foreach($fileData["data"] as $year => $countries)
@foreach ($countries as $country => $dishes)
<option class="year-{{ $year }} hide" value="{{ $country }}">{{ $country }}</option>
@endforeach
@endforeach
</select>

<select id="dish" class="form-control hide">
@foreach($fileData["data"] as $year => $countries)
@foreach ($countries as $country => $dishes)
@foreach ($dishes as $dish => $images)
<option class="year-{{ $year }} country-{{ $country }} hide" value="{{ $dish }}">{{ $dish }}</option>
@endforeach
@endforeach
@endforeach
</select>


So the second and third select are hidden until the previous one is chosen.

Within JavaScript I do

var getSelectedYear = function() {
return $("#year option:selected").val();
}

var getSelectedCountry = function() {
return $("#country option:selected").val();
}

$('#year').change(function() {
$("#country option.year-" + getSelectedYear()).removeClass('hide');
$("#country").removeClass('hide');
})

$('#country').change(function() {
$("#dish option.year-" + getSelectedYear() + ".country-" + getSelectedCountry()).removeClass('hide');
$("#dish").removeClass('hide');
})


So if I choose 2015 in the first select, the second select will display English and french. If I then choose English, the third select will show chips.

This all works fine. My problem is this. If I choose 2015, English and chips, and then change English to french, the third select option now shows chips and mussles instead of just mussles. So it works fine it done in order, but as soon as you change something I need to make the following select options reset before dynamically filling them up.

Is there any way to achieve this?

Answer

What about hiding all of the other options before you unhide the one you want?

$('#year').change(function() {
    // hides all the options
    $("#county option").addClass("hide");
    $("#country option.year-" + getSelectedYear()).removeClass('hide');
    $("#country").removeClass('hide');

    // gets the value of the first available option and resets your dropdown to that
    var first_val = $("#country option:not('.hide')").first().val();
    $("#country").val(first_val);
    // manually trigger the change so that it propagates to the following dropdown
    $("#country").trigger("change");
})

$('#country').change(function() {
    // hides all the options
    $("#dish option").addClass("hide");
    $("#dish option.year-" + getSelectedYear() + ".country-" + getSelectedCountry()).removeClass('hide');
    $("#dish").removeClass('hide');

    // gets the value of the first available option and resets your dropdown to that
    var first_val = $("#dish option:not('.hide')").first().val();
    $("#dish").val(first_val);
})

This adds the "hide" class to all of the available options, then unhides only the specific ones you want to be available. In addition, it selects the first available option so you aren't left with a stale dropdown.