I want to use select2 in knockout.js
for this i have a bindinghandler.
ko.bindingHandlers.select2 = {
init: function(element, valueAccessor, allBindingsAccessor) {
var obj = valueAccessor(),
allBindings = allBindingsAccessor(),
lookupKey = allBindings.lookupKey;
$(element).select2(obj);
if (lookupKey) {
var value = ko.utils.unwrapObservable(allBindings.value);
$(element).select2('data', ko.utils.arrayFirst(obj.data.results, function(item) {
return item[lookupKey] === value;
}));
}
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).select2('destroy');
});
},
update: function(element) {
$(element).trigger('change');
}
};
i use the handler like this:
<select id="itemselector" data-bind="options: items, optionsText: 'Name', OptionsValue:'Id', select2: {}"></select>
now to make custom templates i have to pass a format function to select2 like htis
function formatSelection(item) {
return '<b>' + item.text + '</b>';
}
but i can't figure out how to do this with that binding handle. Can someone explain me how to pass the formatfunction or a string template to the binding handler, so that it will be applied to select?
Just add your option(s) into the {} after the select2 binding declaration. For example:
<select id="itemselector" data-bind="options: items, optionsText: 'Name', optionsValue:'Id', select2: {formatResult: formatSelection}"></select>
Question back at you, the select2 binding that you are using, is a new version to me. How is the lookupKey being used?
Related
I have below code to create Drop-down:
Below code for HTML to render Drop-down as:
<input class="form-control selectedTextBox mobile-space" list="rider" type="text" id="ridername" placeholder="FirstName LastName"
data-bind="trimedValue: item().Name, datalist: {
options: app.viewModel.riderProfiles(),
optionsValue: 'Id',
optionsText: 'Name',
value: app.viewModel.selectedRiderId
}" />
Below is Knockout.js handler:
ko.bindingHandlers.datalist = (function () {
function getVal(rawItem, prop) {
var item = ko.unwrap(rawItem);
return item && prop ? ko.unwrap(item[prop]) : item;
}
function findItem(options, prop, ref) {
return ko.utils.arrayFirst(options, function (item) {
return ref === getVal(item, prop);
});
}
return {
init: function (element, valueAccessor, allBindingsAccessor) {
var setup = valueAccessor(),
textProperty = ko.unwrap(setup.optionsText),
valueProperty = ko.unwrap(setup.optionsValue),
dataItems = ko.unwrap(setup.options),
myValue = setup.value,
koValue = allBindingsAccessor().value,
datalist = document.createElement("DATALIST");
// create an associated <datalist> element
datalist.id = element.getAttribute("list");
document.body.appendChild(datalist);
// when the value is changed, write to the associated myValue observable
function onNewValue(newVal) {
var dataItems = ko.unwrap(setup.options),
selectedItem = findItem(dataItems, textProperty, newVal),
newValue = selectedItem ? getVal(selectedItem, valueProperty) : void 0;
if (ko.isWriteableObservable(myValue)) {
myValue(newValue);
}
}
// listen for value changes
// - either via KO's value binding (preferred) or the change event
if (ko.isSubscribable(koValue)) {
koValue.subscribe(onNewValue);
} else {
ko.utils.registerEventHandler(element, "change", function () {
onNewValue(this.value);
});
}
// init the element's value
// - either via the myValue observable (preferred) or KO's value binding
if (ko.isObservable(myValue) && myValue()) {
element.value = getVal(findItem(dataItems, valueProperty, myValue()), textProperty);
} else if (ko.isObservable(koValue) && koValue()) {
onNewValue(koValue());
}
},
update: function (element, valueAccessor) {
var setup = valueAccessor(),
datalist = element.list,
dataItems = ko.unwrap(setup.options),
textProperty = ko.unwrap(setup.optionsText);
// rebuild list of options when an underlying observable changes
datalist.innerHTML = "";
ko.utils.arrayForEach(dataItems, function (item) {
var option = document.createElement("OPTION");
option.value = getVal(item, textProperty);
datalist.appendChild(option);
});
ko.utils.triggerEvent(element, "change");
}
};})();
And with only MAC(OS) & Safari (Web-Browser) below error message is shown as:
Message: Unable to process binding "datalist: function () {return { options:app.viewModel.riderProfiles(),optionsValue:'Id',optionsText:'Name',value:app.viewModel.selectedRiderId} }"
Message: undefined is not an object (evaluating 'u.innerHTML=""')
The HTML element contains a set of elements that represent the values available for other controls.
But "Safari" browser does not support it.
I have the following client-side code:
var ProfileManager = function () {
self.SelectedLanguage = ko.observable();
self.SelectedLanguage.subscribe(function (newValue) {
alert("The person's new name is " + newValue);
});
var bindUIwithViewModel = function (viewModel) {
ko.applyBindings(viewModel);
};
}
and I later do bindUIwithViewModel(self);.
and a HTML select bound to SelectedLanguage:
<select id="selectAvailableLanguages" class="form-control language-select" data-bind="options: AvailableLanguages, optionsText: 'Code', value : SelectedLanguage"></select>
The select gets populated successfully, the value inside SelectedLanguage observable changes, but the alert just won't show up. Any ideas?
Also, don't know if related but the observe array inside __ko.mapping_ is an array[0]..
Please check the fiddle. Note, "AvailableLanguages" and "SelectedLanguage" properties should exist in the same context, i.e. belong the binded view model.
I've modified your JS code:
var ProfileManager = function () {
self.SelectedLanguage = ko.observable();
self.SelectedLanguage.subscribe(function (newValue) {
alert("The person's new name is " + JSON.stringify(newValue));
});
self.AvailableLanguages = [ { Code: 'c++', Person: 'John' }, { Code: 'c#', Person: 'Mark' } ]
}
ko.applyBindings(new ProfileManager());
I try to binding two computed select with Knockout:
- the first select(DropDownLinee) is filled when on page load
- the second select(DropDownCorse) is filled when the user select an item on the first select
This is the example:
<select id="DropDownLinee" data-bind="options: ArrayLinee, optionsText: 'NomeLinea', optionsValue: 'NomeLinea', value: selectedLinea " data-toggle="dropdown"></select>
<select id="DropDownCorse" data-bind="options: ArrayCorse, optionsText: 'CodiceCorsa', optionsValue: 'CodiceCorsa', value: selectedCorsa " data-toggle="dropdown"></select>
function LineeViewModel() {
var self = this;
self.selectedLinea = ko.observable();
self.selectedCorsa = ko.observable();
self.ArrayLinee = ko.observableArray([]);
self.ArrayCorse = ko.observableArray([]);
$.getJSON('/Home/GetLines', function (data) {
self.ArrayLinee(data);
});
self.ArrayCorse = ko.computed(function () {
$.getJSON('/Home/GetRides',
{
LineaSelezionata: self.selectedLinea(),
DirezioneSelezionata: $('input[name=radio4]:checked', '.areaselezione').val()
},
function (data) {
debugger;
self.ArrayCorse(data);
});
});
}
lineeVM = new LineeViewModel();
ko.applyBindings(lineeVM);
I have this error when i check to load the 'DropDownCorse':
Uncaught Error: Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.
Can anyone help me to solve this problem???
Thank in advance greetings Donato
You want to use subscribe, not a computed.
self.selectedLinea.subscribe(function (newSelection) {
$.getJSON('/Home/GetRides',
{
LineaSelezionata: newSelection,
DirezioneSelezionata: $('input[name=radio4]:checked', '.areaselezione').val()
},
function (data) {
debugger;
self.ArrayCorse(data);
});
});
I have a dropdown and data binded to it as below
HTML:
<div>
<label>Notice Type</label>
<select id="ntctype" data-bind="options: NoticeType, value: selectedNoticeType, optionsCaption:'Choose...', optionsValue:'NoticeTypeID', optionsText:'NoticeTypeDescription'"></select>
</div>
KO JS:
self.NoticeType = ko.observableArray([]);
self.selectedNoticeType = ko.observable();
$.getJSON("GetNoticeType", null, function (data) {
self.NoticeType(data);
}
);
the NoticeType array looks like this
[{"NoticeTypeID":1,"NoticeTypeDescription":"Close"},{"NoticeTypeID":2,"NoticeTypeDescription":"Open"}]
I would like to set the deafult value as Close after binding.I tried using optionsAfterRender & ko.applybindingstoNode none of them worked.
What would be the clean and neat approach to do this?
As mentioned in the comments you just need to set default value to value binded observable in viewModel
View Model :
function accountViewModel() {
var self = this;
self.NoticeType = ko.observableArray();
self.selectedNoticeType = ko.observable();
self.ajaxcall = function () {
self.NoticeType([{
"NoticeTypeID": 1,
"NoticeTypeDescription": "Close"
}, {
"NoticeTypeID": 2,
"NoticeTypeDescription": "Open"
}]);
self.selectedNoticeType = ko.observable(1);
}
self.ajaxcall();
}
Working fiddle here
I want to know what the previous value is from a Dropdown list.
In the following html I can set the Options and the currently selected.
<select data-bind="options: group_128,
optionsText: 'description',
value: selectedgroup_128,
event: { change: selectionChanged_group_128 }">
</select>
in the Javascript / viewModel I do :
selectionChanged_group_128 = function (data, event) {
self.addItemClicked2(self.selectedgroup_128, event)
};
At this point I want to know what the previous selected item was to send it to the addItemClicked2.
You could subscribe to the observable to get the value before it changed:
self.selectedgroup_128.subscribe(function(oldValue) {
self.selectedgroup_128.previousValue = oldvalue;
}, null, "beforeChange");
Now you can get the previous value like this:
self.selectedgroup_128.previousValue
Why not just change your model to store the new value as previous value?
http://jsfiddle.net/uLeDP/
var ViewModel = function() {
this.group_128 = ko.observable([{description:"first"},{description:"second"}]);
this.selectedgroup_128 = ko.observable("first");
this.prevgroup_128 = null;
this.selectionChanged_group_128 = function(val) {
alert("Now I'm " + this.selectedgroup_128().description + " but I was " + this.prevgroup_128);
this.prevgroup_128 = this.selectedgroup_128().description;
}
};