kate_hudson kate_hudson - 3 months ago 11
Ajax Question

Dynamic select options based on previous selections

I asked a similar question a while ago but realised that I was going about it the wrong way. I have an array of data, can make it json data if required. The data looks like the following

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"
]
]
]
]
]


The structure is pretty standard, Year>Country>Dish>Images. Inside my view, I have a select input that displays the years.

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


Based on the selected year, I then need to display a second option showing the available countries. So if they choose 2015, the next select options should display english and french. So, I am going to use Ajax for this. At the moment I have the following

$('#yearSelection').change(function() {
var selectedYear = $("#yearSelection option:selected").val();

$.ajax({
type: "POST",
url: "./productChoices",
data: { year : selectedYear }
}).done(function(data){

});
});


Its not much, but its a start. So in my controller, I can now access year which will give me the selected year. I then plan on passing back the html for the next select input.

My problem is this. In the html, you can see that my select is being created from a foreach loop, looping the array $fileData. When I make a selection, I need to pass the selected year which I am doing, but I also need to pass the $fileData array so I can work out which data I need to display in my next select, which will be done in my controller. So how can I also pass $fileData along with the Ajax request. It is not a html element so I am not too sure how.

Thanks

Answer

If your dataset isn't very large, you can make it 100% without ajax and have a fastest user response.

1st: Make your three selects with all available options. Here I've iterated on your array to draw the options, and added some "filter" classes that will be used by javascript.

<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>

2st: At Javascript:

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');
})

$('#dish').change(function() {
    // Do what you want with the selected dish, you didn't specified if you want to show the images somewhere.
})

Note that this code is incomplete, you will need to reset everything to original state when a previous select was changed, and also I didn't anything with your images.

Comments