JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<link rel="Stylesheet" href="styles.css" />
<script type="text/javascript" src="../lib/jquery.tmpl.js"></script>
<script type="text/javascript" src="../lib/json2.js"></script>
<script type="text/javascript" src="../build/output/knockout-latest.min.js"></script>
<!-- Referencing jQuery autocomplete -->
<link rel="stylesheet" href="http://dev.jquery.com/view/trunk/plugins/autocomplete/jquery.autocomplete.css" type="text/css" />
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/autocomplete/lib/jquery.bgiframe.min.js"></script>
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/autocomplete/jquery.autocomplete.js"></script>
</head>
<body>
<table>
<thead>
<tr>
<th>Make</th>
<th>Model</th>
<th>Type</th>
<th>Engine</th>
</tr>
</thead>
<tbody data-bind="template: { name: 'vehicleRowTemplate', foreach: lines }"></tbody>
</table>
<script type="text/html" id="vehicleRowTemplate">
<tr>
<td><input data-bind="autocomplete: SuggestedMakes, value: Make, valueUpdate: 'afterkeydown'" /></td>
<td><input data-bind="autocomplete: SuggestedModels, value: Model, valueUpdate: 'afterkeydown'" /></td>
<td><input data-bind="autocomplete: SuggestedTypes, value: Type, valueUpdate: 'afterkeydown'" /></td>
<td><input data-bind="autocomplete: SuggestedEngines, value: Engine, valueUpdate: 'afterkeydown'" /></td>
</tr>
</script>
</body>
</html>
JavaScript
var SuggestedMakes = ko.observableArray(["Ford", "Renault", "Nissan"]);
var vehicleLine = function(){
this.Make = ko.observable('');
this.Model = ko.observable('');
this.Type = ko.observable('');
this.Engine = ko.observable('');
this.SuggestedModels = ko.observableArray();
this.SuggestedTypes = ko.observableArray();
this.SuggestedEngines = ko.observableArray();
this.Make.subscribe(function() {
var make = this.Make();
this.SuggestedModels([]); // Erase any existing suggestions
setTimeout(function() {
// Using hard-coded data, but simulating slow asynchronous load via setTimeout
// An Ajax call would behave the same.
var result;
switch (make) {
case "Ford": result = ["Capri", "Mondeo", "Focus"]; break;
case "Renault": result = ["Megane", "Cleo", "Scenic"]; break;
case "Nissan": result = ["Micra", "Primera", "Navara"]; break;
}
this.SuggestedModels(result);
}.bind(this), 1000);
}.bind(this));
// Todo: also populate this.SuggestedTypes and this.SuggestedEngines in a similar way
};
var vehicles = function() {
this.lines = ko.observableArray([new vehicleLine(), new vehicleLine()]);
};
ko.bindingHandlers.autocomplete = {
update: function(element, list, allBindings) {
$(element).autocomplete().trigger("setOptions", { data: ko.utils.unwrapObservable(list) });
}
};
var vehicleViewModel = new vehicles();
ko.applyBindings(document.body, vehicleViewModel);