Knockout Combo
by Ben Clayton
HTML
<div style="height:100px"></div>
<combo-widget params="value:123"></combo-widget>
<HR>
<combo-widget params="value:789"></combo-widget>
CSS
.ncselect {
position: relative;
}
.optionlist {
border: 1px solid gray;
width: 225px;
max-height: 200px;
overflow: auto;
position:absolute;
z-index:2;
bottom:28px;
background-color:#FFFFFF;
}
.selectinput {
width: 200px;
}
.ipwrapper {
display: inline-block;
position: relative;
}
.ipwrapper input {
height: 20px;
}
.combotrigger {
font-family: arial;
font-weight:bold;
line-height: 24px;
display: inline-block;
position: relative;
background-color: white;
width: 20px;
height: 24px;
cursor: pointer;
text-align: center;
border: 1px solid #C0C0C0;
left: -4px;
top: 1px;
}
JavaScript
ko.components.register('combo-widget', {
viewModel: function(params) {
var self = this;
self.value = ko.observable(params.value);
self.optionsOpen = ko.observable(false);
self.people = ko.observableArray([{
firstName: "Bert",
lastName: "Bertington"
},{
firstName: "Bess",
lastName: "Bessington"
}]);
self.openCombo = function() {
this.optionsOpen( ! this.optionsOpen() );
}.bind(this);
self.addPerson = function() {
self.people.push({
firstName: "first ",
lastName: "last "
});
}.bind(this);
self.selectFromList = function(option) {
this.value(option.firstName);
this.optionsOpen(false);
}.bind(this);
self.removePerson = function() {
self.people.remove(this);
}.bind(this);
self.currentFilter = ko.observable(); // property to store the filter
self.filterProducts = ko.computed(function() {
if(!this.currentFilter()) {
return this.people();
} else {
return ko.utils.arrayFilter(this.people(), function(option) {
return option.firstName == this.currentFilter();
}.bind(this));
}
}.bind(this));
self.filter = function() {
this.currentFilter( this.value() );
}.bind(this);
},
template:
'<div class="ncselect">\
<div class="optionlist" data-bind="visible: optionsOpen">\
<table>\
<tbody data-bind="foreach: people" >\
<tr data-bind="click: $parent.selectFromList" >\
<td data-bind="text: firstName" ></td>\
<td data-bind="text: lastName" > </td>\
</tr>\
</tbody>\
</table>\
</div>\
<div class="ipwrapper" >\
<input class="selectinput" type="text" data-bind="value: value, event: { keypress: filter}" />\
<div data-bind="click: openCombo" class="combotrigger">v</div>\
</div>\
<button data-bind="click: addPerson">Add</button>\
...