JSFiddle - React, Tailwind, and code Playground
by Ori Hochman
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div class="panel-body">
<div class="form-group">
<label for="availableCitiesSelectControl" class="control-label">Select a City</label>
<select class="form-control" id="availableCitiesSelectControl" data-bind="foreach: availableCities, value: selectedCity, valueAllowUnset: true">
<optgroup data-bind="attr: {label: regionName}, foreach: cities">
<option data-bind="text: cityName"></option>
</optgroup>
</select>
</div>
<div class="form-group">
<label for="availableStreetSelectControl" class="control-label">Select a Street</label>
<select class="form-control" id="availableStreetSelectControl" data-bind="foreach: availbleStreets, value: selectedStreet, valueAllowUnset: true">
<option value="">Select street...</option>
<optgroup data-bind="attr: {label: cityName}, foreach: streets">
<option data-bind="text: streetName"></option>
</optgroup>
</select>
</div>
<div class="form-group">
<label for="" class="control-label">Selected City</label>
<input type="text" data-bind="value: selectedCity" disabled />
</div>
<div class="form-group">
<label for="" class="control-label">Selected Street</label>
<input type="text" data-bind="value: selectedStreet" disabled />
</div>
</div>
JavaScript
var ViewModel = function() {
var self = this;
var regionAndCityArray = [{
regionName: "Europe",
cities: [{
cityName: "London",
additionalUnimportantInformation: 100
}, {
cityName: "Paris",
additionalUnimportantInformation: 200
}]
}, {
regionName: "North America",
cities: [{
cityName: "New York",
additionalUnimportantInformation: 45
}]
}];
var cityAndStreetArray = [{
cityName: "London",
streets: [{
streetName: "Parker",
streetLength: 5
}, {
streetName: "Macklin",
streetLength: 10
}, ]
}, {
cityName: "New York",
streets: [{
streetName: "5th Avenue",
streetLength: 3
}, {
streetName: "Park Ave",
streetLength: 12
}]
}, {
cityName: "Paris",
streets: [{
streetName: "Rue de Turbigo",
streetLength: 11
}, {
streetName: "Rue aux Ours",
streetLength: 12
}]
}];
var getAvailableStreets = function() {
var availableStreets = cityAndStreetArray;
var selectedCity = self.selectedCity();
var selectedRegion = _.find(regionAndCityArray,
function(region) {
return _.find(region.cities,
function(city) {
return city.cityName === selectedCity;
});
});
if (selectedRegion == undefined) {
return availableStreets;
}
var filteredStreets = _.filter(cityAndStreetArray,
function(city) {
return city.cityName === selectedCity;
});
return filteredStreets;
}
self.availableCities = ko.observableArray(regionAndCityArray);
self.selectedCity = ko.observable();
self.availbleStreets = ko.computed(getAvailableStreets);
self.selectedStreet = ko.observable();
};
var viewModel = new ViewModel();
viewModel.selectedCity.subscribe(function() {
viewModel.selectedStreet('');
}, viewModel);
...