Основываясь на других ответах, вот первый вариант использования с нокаутом:
Использование
<div data-bind="editableSelect: {options: optionsObservable, value: nameObservable}"></div>
Связывание данных с нокаутом
composition.addBindingHandler('editableSelect',
{
init: function(hostElement, valueAccessor) {
var optionsObservable = getOptionsObservable();
var valueObservable = getValueObservable();
var $editableSelect = $(hostElement);
$editableSelect.addClass('select-editable');
var editableSelect = $editableSelect[0];
var viewModel = new editableSelectViewModel(optionsObservable, valueObservable);
ko.applyBindingsToNode(editableSelect, { compose: viewModel });
//tell knockout to not apply bindings twice
return { controlsDescendantBindings: true };
function getOptionsObservable() {
var accessor = valueAccessor();
return getAttribute(accessor, 'options');
}
function getValueObservable() {
var accessor = valueAccessor();
return getAttribute(accessor, 'value');
}
}
});
View
<select
data-bind="options: options, event:{ focus: resetComboBoxValue, change: setTextFieldValue} "
id="comboBox"
></select>
<input
data-bind="value: value, , event:{ focus: textFieldGotFocus, focusout: textFieldLostFocus}"
id="textField"
type="text"/>
ViewModel
define([
'lodash',
'services/errorHandler'
], function(
_,
errorhandler
) {
var viewModel = function(optionsObservable, valueObservable) {
var self = this;
self.options = optionsObservable();
self.value = valueObservable;
self.resetComboBoxValue = resetComboBoxValue;
self.setTextFieldValue = setTextFieldValue;
self.textFieldGotFocus = textFieldGotFocus;
self.textFieldLostFocus = textFieldLostFocus;
function resetComboBoxValue() {
$('#comboBox').val(null);
}
function setTextFieldValue() {
var selection = $('#comboBox').val();
self.value(selection);
}
function textFieldGotFocus() {
$('#comboBox').addClass('select-editable-input-focus');
}
function textFieldLostFocus() {
$('#comboBox').removeClass('select-editable-input-focus');
}
};
errorhandler.includeIn(viewModel);
return viewModel;
});
CSS
.select-editable {
display: block;
width: 100%;
height: 31px;
padding: 6px 12px;
font-size: 12px;
line-height: 1.42857143;
color: #555555;
background-color: #ffffff;
background-image: none;
border: 1px solid #cccccc;
border-radius: 0px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;padding: 0;
}
.select-editable select {
outline:0;
padding-left: 10px;
border:none;
width:100%;
height: 29px;
}
.select-editable input {
outline:0;
position: relative;
top: -27px;
margin-left: 10px;
width:90%;
height: 25px;
border:none;
}
.select-editable select:focus {
outline:0;
border: 1px solid #66afe9;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
}
.select-editable input:focus {
outline:0;
}
.select-editable-input-focus {
outline:0;
border: 1px solid #66afe9 !important;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
}