katie hudson
katie hudson

Reputation: 2893

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

Upvotes: 0

Views: 108

Answers (2)

Abdul
Abdul

Reputation: 472

When you got the year from your ajax call, you can select that year from your array. Let's say you passed year 2015. now you do the following:

$year = '2015'; // got from ajax
$country = $data[$year];

Now your $country will contain the following data:

array:2 [▼
      "english" => array:1 [▼
        "chips" => array:1 [▼
          0 => "img1.png"
        ]
      ]
      "french" => array:1 [▼
        "mussles" => array:1 [▼
          0 => "img1.png"
        ]
      ]
    ]

Now you will have to return the $country from ajax call as json data and add them to your next select input. Let's say you have select element id as countries, So you can add country list as below:

var selectValues = data; // country list got from your controller
$.each(selectValues, function(key, value) {   
     $('#countries')
         .append($("<option></option>")
                    .attr("value",key)
                    .text(key)); // option value and text, both will be country.  
});

I hope that helps

Upvotes: 1

Elias Soares
Elias Soares

Reputation: 10254

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.

Upvotes: 1

Related Questions