I followed the Knockout tutorials some time ago of which one of them http://learn.knockoutjs.com/#/?tutorial=collections
details how to creating lists and collections. However I want to create a cascading drop down select within the list.
My question would have been can you create a cascading drop down in a dynamic list like this using knockout?
As it happens I've actually managed to solve the question after a couple of hours of looking into it so will add it here as an answer as I think it could be useful for someone. Maybe there are better ways of doing it?
It would work, but I would just add one thing: small caching. Basically, once you've loaded the meals available for a given meal you could create a property in your meal object to store them. That way, subsequent calls may know that these meals have already been loaded. I've created an observable array for that, like so:
Given this function which simulates retrieving data from the server:
var mealTypesByKey = [];
mealTypesByKey[1] = [{ mealName: "Vegemite Sandwich", price: 4.00, mealType: 1},
{ mealName: "Cheese Sandwich", price: 34.95,mealType: 2 },
{ mealName: "Jam Sandwich", price: 290, mealType: 3 } ];
mealTypesByKey[2] = [{ mealName: "Standard (Ham)", price: 15, mealType: 1},
{ mealName: "Chicken Wrap (Possibly rat)", price: 15, mealType: 1} ];
mealTypesByKey[3] = [{ mealName: "Premium (lobster)", price: 34.95,mealType: 2 },
{ mealName: "Ultimate (whole zebra)", price: 290, mealType: 3 } ];
function serverGetMealsForType(key) {
return mealTypesByKey[key];
}
You can define the following subscribable function:
self.mealType.subscribe(function(newMealType) {
if(!newMealType.meals) {
newMealType.meals = ko.observableArray([]);
newMealType.meals(serverGetMealsForType(newMealType.key));
console.log("meals loaded");
} else {
console.log("meals already available for meal type " + newMealType.key);
}
});
And that way, the dynamic list is recreated properly with the given binding:
<td><select data-bind="options: mealType().meals, value: meal, optionsText: 'mealName'"></select></td>
This is a common and easy technique to avoid unneeded server calls.
Edit: forgot to add the fiddle I've forked.