Skip to content

Instantly share code, notes, and snippets.

@studgeek
Created September 13, 2011 16:30
Show Gist options
  • Save studgeek/1214258 to your computer and use it in GitHub Desktop.
Save studgeek/1214258 to your computer and use it in GitHub Desktop.
knockout autocomplete
<input data-bind="jqAuto: { autoFocus: true }, jqAutoSource: myPeople, jqAutoValue: mySelectedGuid, jqAutoSourceLabel: 'displayName', jqAutoSourceInputValue: 'name', jqAutoSourceValue: 'guid'" />
<hr/>
<div data-bind="text: mySelectedGuid() ? mySelectedGuid() : 'None selected'"></div>
<hr/>
For testing setting the model value elsewhere:
<select data-bind="options: myPeople, optionsCaption: 'select a person...', optionsText: 'displayName', optionsValue: 'guid', value: mySelectedGuid"></select>
<hr/>
//jqAuto -- main binding (should contain additional options to pass to autocomplete)
//jqAutoSource -- the array of choices
//jqAutoValue -- where to write the selected value
//jqAutoSourceLabel -- the property that should be displayed in the possible choices
//jqAutoSourceInputValue -- the property that should be displayed in the input box
//jqAutoSourceValue -- the property to use for the value
ko.bindingHandlers.jqAuto = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var options = valueAccessor() || {},
allBindings = allBindingsAccessor(),
unwrap = ko.utils.unwrapObservable,
modelValue = allBindings.jqAutoValue,
source = unwrap(allBindings.jqAutoSource),
valueProp = allBindings.jqAutoSourceValue,
inputValueProp = allBindings.jqAutoSourceInputValue || valueProp,
labelProp = allBindings.jqAutoSourceLabel || inputValueProp;
//function that is shared by both select and change event handlers
function writeValueToModel(valueToWrite) {
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 );
}
}
//on a selection write the proper value to the model
options.select = function(event, ui) {
writeValueToModel(ui.item ? ui.item.actualValue : null);
};
//on a change, make sure that it is a valid value or clear out the model value
options.change = function(event, ui) {
var currentValue = $(element).val();
var matchingItem = ko.utils.arrayFirst(source, function(item) {
return unwrap(item[inputValueProp]) === currentValue;
});
if (!matchingItem) {
writeValueToModel(null);
}
}
//handle the choices being updated in a DO, to decouple value updates from source (options) updates
var mappedSource = ko.dependentObservable(function() {
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 = inputValueProp ? unwrap(item[inputValueProp]) : unwrap(item).toString(); //show in input box
result.actualValue = valueProp ? unwrap(item[valueProp]) : item; //store in model
return result;
});
return mapped;
});
//whenever the items that make up the source are updated, make sure that autocomplete knows it
mappedSource.subscribe(function(newValue) {
$(element).autocomplete("option", "source", newValue);
});
options.source = mappedSource();
//initialize autocomplete
$(element).autocomplete(options);
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
//update value based on a model change
var allBindings = allBindingsAccessor(),
unwrap = ko.utils.unwrapObservable,
modelValue = unwrap(allBindings.jqAutoValue),
valueProp = allBindings.jqAutoSourceValue,
inputValueProp = allBindings.jqAutoSourceInputValue || valueProp;
//if we are writing a different property to the input than we are writing to the model, then locate the object
if (valueProp && inputValueProp !== valueProp) {
var source = unwrap(allBindings.jqAutoSource) || [];
var modelValue = ko.utils.arrayFirst(source, function(item) {
return unwrap(item[valueProp]) === modelValue;
}) || {};
}
//update the element with the value that should be shown in the input
$(element).val(modelValue && inputValueProp !== valueProp ? unwrap(modelValue[inputValueProp]) : modelValue.toString());
}
};
function Person(guid, name, email) {
this.guid = ko.observable(guid);
this.name = ko.observable(name);
this.email = ko.observable(email);
this.displayName = ko.dependentObservable(function() {
return this.name() + " [" + this.email() + "]";
}, this);
}
var viewModel = {
myPeople: ko.observableArray([
new Person("5658ff20-f230-4176-97d1-0ac21abfdbdf", "Bob Smith", "bsmith@company.com"),
new Person("1d7b9b28-25b7-40de-bec1-0a5426228f5b", "Bonnie Johnson", "bjohnson@company.com"),
new Person("28605d66-d794-4a09-8452-0278abd690c6", "John Daniels", "jdaniels@company.com"),
new Person("7c4881ef-5530-45c9-96eb-5dceed6cd4c9", "Deborah Danielson", "ddanielson@company.com"),
new Person("ec361d63-38ae-4ecc-ab46-6c0ef19ed3ac", "John Daniels", "jxdaniels@company.com")
]),
mySelectedGuid: ko.observable("ec361d63-38ae-4ecc-ab46-6c0ef19ed3ac")
};
ko.applyBindings(viewModel);
name: jQuery UI autocomplete - original rniemeyer version
description: knockout autocomplete, see https://groups.google.com/d/topic/knockoutjs/ABhEeI7jLKA/discussion
authors:
- rniemeyer
resources:
- jsfiddle-defaults.user.js
- http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/base/jquery-ui.css
- http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js
- http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-latest.debug.js
normalize_css: no
// ==UserScript==
// @name Sensible defaults for jsFiddle.
// @author Mathias Bynens <http://mathiasbynens.be/>
// @link http://mths.be/bde
// @match http://jsfiddle.net/*
// ==/UserScript==
// Insert JS before </body> and don’t use any libraries by default
[].forEach.call(document.querySelectorAll('#js_wrap option[value="b"], #js_lib option[value="11"]'), function(el) {
el.selected = true;
});
// Don’t use the “normalized” CSS (it’s more like a reset anyway)
document.getElementById('id_normalize_css').checked = false;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment