A Small Form and Cascading Drop Down with KnockoutJS
by Avi Algaly
HTML
<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.2.0.debug.js"></script>
<fieldset>
<div class="field">
<label for="resident-name">Resident Name</label>
<input type="text" id="resident-name" data-bind="value: residentName, valueUpdate: 'afterkeydown'" />
</div>
<div class="field">
<label for="street-name">Street</label>
<input type="text" id="street-name" data-bind="value: streetName, valueUpdate: 'afterkeydown'" />
</div>
<div class="field">
<label for="number-name">Number</label>
<input type="text" id="number-name" data-bind="value: numberName, valueUpdate: 'afterkeydown'" />
</div>
<div class="field">
<label for="country-name">CountryName</label>
<select id="country-name" data-bind="options: availableCountries, optionsText: 'name', optionsCaption: 'Choose Country...', value: countryName"></select>
</div>
<div class="field">
<label for="city-name">City Name</label>
<select id="city-name" data-bind="options: availableCities, optionsText: 'cityName', optionsCaption: 'Choose City...', value: cityName"></select>
</div>
<button id="submit-command" data-bind="click: submitClick, enable: validateModel">Submit</button>
</fieldset>
<br/>
<button id="show-info-command" >Show Info</button>
SCSS
body {
font-family: Arial, Verdana;
}
fieldset {
width: 500px;
padding: 20px;
background: #f0f0f0;
overflow:auto;
/* Border style */
border: 1px solid #cccccc;
border-radius: 7px;
box-shadow: 2px 2px 2px #cccccc;
.field {
float: left;
clear: both;
}
label {
text-shadow: 2px 2px 2px #ccc;
display: block;
float: left;
width: 120px;
line-height: 25px;
font-size: 15px;
}
input, select {
font-size: 15px;
padding: 5px;
border: 1px solid #b9bdc1;
color: #797979;
float: left;
margin-bottom: 5px;
width: 130px;
}
select {
width: (130 + 10)px;
}
button {
float: right;
clear: both;
margin:10px 55px 10px 0;
font-weight: bold;
line-height: 1;
padding: 6px 10px;
cursor:pointer;
color: #fff;
text-align: center;
text-shadow: 0 -1px 1px #64799e;
/* Background gradient */
background: #a5b8da;
background: -moz-linear-gradient(top, #a5b8da 0%, #7089b3 100%);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#a5b8da), to(#7089b3));
/* Border style */
border: 1px solid #5c6f91;
border-radius: 10px;
/* Box shadow */
box-shadow: inset 0 1px 0 0 #aec3e5;
&[disabled] {
opacity: 0.5;
}
}
}
JavaScript
var newPropertyViewModel = {
residentName: ko.observable("John Doe"),
streetName: ko.observable("Sesame"),
numberName: ko.observable("5"),
cityName: ko.observable(""),
countryName: ko.observable(""),
availableCountries: ko.observableArray([]),
submitClick: function() {
alert("Submitting data...");
}
};
newPropertyViewModel.availableCities = ko.dependentObservable(function(currentCity) {
var country = this.countryName();
var availableCities = {
cities: []
};
if (country) {
availableCities = ko.utils.arrayFilter(citiesByCountry, function(currentCity) {
return currentCity.countryId === country.id;
});
}
//if (availableCities.length && availableCities.length > 0) {
// availableCities = availableCities[0];
//}
return availableCities;
}, newPropertyViewModel);
newPropertyViewModel.validateModel = ko.computed(function() {
var isValid = (this.residentName() || false) && (this.streetName() || false) && (this.numberName() || false) && (this.cityName() || false) && (this.countryName() || false);
return isValid;
}, newPropertyViewModel);
ko.applyBindings(newPropertyViewModel);
$("#show-info-command").on("click", function() {
var currentState = {
residentName: newPropertyViewModel.residentName(),
streetName: newPropertyViewModel.streetName(),
numberName: newPropertyViewModel.numberName(),
cityName: newPropertyViewModel.cityName(),
countryName: newPropertyViewModel.countryName()
};
alert(JSON.stringify(currentState));
//alert(ko.utils.toJSON(newPropertyViewModel));
});
// load countries
var countries = [
{
id: 1,
name: "Israel"},
{
id: 2,
name: "USA"},
{
id: 3,
name: "Canada"}
];
// load cities
var citiesByCountry = [
{
"countryId": 0,
"id": 0,
"cityName": "choose"
},
{
"countryId": 1,
"id": 2,
"cityName":...