Reputation: 119
I'm using a nice custom binding to populate an JQueryUI auto complete, but I want to customize it to return the Item object, which I can then push to a different array.; Could anyone shed any light on how to do this? Thanks!
http://jsfiddle.net/rniemeyer/kEdT5/
<input data-bind="jqAuto: { autoFocus: true }, jqAutoSource: myOptions, jqAutoValue: mySelectedOption, jqAutoSourceLabel: 'name', jqAutoSourceValue: 'id'" />
<hr/>
<div data-bind="text: ko.toJSON(mySelectedOption)"></div>
//jqAuto -- additional options to pass to autocomplete
//jqAutoSource -- the array of choices
//jqAutoValue -- where to write the selected value
//jqAutoSourceLabel -- the property name that should be displayed in the possible choices
//jqAutoSourceValue -- the property name to use for the value
ko.bindingHandlers.jqAuto = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var options = valueAccessor() || {};
var allBindings = allBindingsAccessor();
var unwrap = ko.utils.unwrapObservable;
//handle value changing
var modelValue = allBindings.jqAutoValue;
if (modelValue) {
var handleValueChange = function(event, ui) {
var valueToWrite = ui.item ? ui.item.value : $(element).val();
if (ko.isWriteableObservable(modelValue)) {
modelValue(valueToWrite );
} else { //write to non-observable
if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers']['jqAutoValue'])
allBindings['_ko_property_writers']['jqAutoValue'](valueToWrite );
}
};
options.change = handleValueChange;
options.select = handleValueChange;
}
//handle the choices being updated in a DO, so the update function doesn't have to do it each time the value is updated
var mappedSource = ko.dependentObservable(function() {
var source = unwrap(allBindings.jqAutoSource);
var valueProp = unwrap(allBindings.jqAutoSourceValue);
var labelProp = unwrap(allBindings.jqAutoSourceLabel) || valueProp;
var mapped = ko.utils.arrayMap(source, function(item) {
var result = {};
result.label = labelProp ? unwrap(item[labelProp]) : unwrap(item).toString(); //show in pop-up choices
result.value = valueProp ? unwrap(item[valueProp]) : unwrap(item).toString(); //value
return result;
});
return mapped;
});
mappedSource.subscribe(function(newValue) {
$(element).autocomplete("option", "source", newValue);
});
options.source = mappedSource();
$(element).autocomplete(options);
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
//update value based on a model change
var allBindings = allBindingsAccessor();
var modelValue = allBindings.jqAutoValue;
if (modelValue) {
$(element).val(ko.utils.unwrapObservable(modelValue));
}
}
};
function Item(id, name) {
return {
id: ko.observable(id),
name: ko.observable(name)
};
}
var viewModel = {
myOptions: ko.observableArray([
new Item("One", "1 - One description"),
new Item("Two", "2 - Two description"),
new Item("Three", "3- Three description"),
new Item("Four", "4- Four description"),
new Item("Five", "5- Five description")
]),
mySelectedOption: ko.observable()
};
ko.applyBindings(viewModel);
Upvotes: 0
Views: 5884
Reputation: 2887
You can add a small timeout that fixes it:
...
select: function (event, ui) {
var selectedItem = ui.item;
window.setTimeout(function () {
$(element).val(selectedItem.koObservableValue);
}, 10);
}
In case it's a simple value
...
select: function (event, ui) {
var selectedItem = ui.item;
window.setTimeout(function () {
$(element).val(selectedItem);
}, 10);
}
Upvotes: 1
Reputation: 114792
There was an updated version of that autocomplete binding in this post: How to create an auto-complete combobox?. It separated the value shown in the input box from the value written. If you leave the jqAutoSourceValue
off, then it will write the entire object.
Here is a sample: http://jsfiddle.net/rniemeyer/3vqpP/
Upvotes: 1
Reputation: 1316
You can add some logic to the select function of the jQuery UI autocomplete. Is placed inside binding handler:
if (modelValue) {
var handleValueChange = function(event, ui) {
...
}
I made some changes to your example. It's not perfect but it can be a start point, I hope. http://jsfiddle.net/dima_k/kEdT5/37/
Upvotes: 1