Im working with knockout.js and select2 plugin.
Im trying to change the select2 ajax url based on a value of an observable.
for example if based on some selection i do ajax call to 1 url or another.
Here is a sample code:
<input type="hidden" data-bind="bobox: { optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Избери...', sourceUrl: partnerUrl }, value: ApplyToSubject" id="ApplyToSubject" name="ApplyToSubject">
This is how the sourceUrl: partnerUrl is retrieved:
self.partnerUrl = koputed(function () {
var value = "";
if (something)
{
value = apiUrls.customer;
}
else if (something else)
{
value = apiUrls.vendor;
}
else if(or another thing)
{
value = apiUrls.employee;
}
return value;
});
I work with custom binding. Here is the code for it:
// documentation /
ko.bindingHandlersbobox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var obj = valueAccessor(),
allBindings = allBindingsAccessor();
var optionsText = ko.utils.unwrapObservable(obj.optionsText);
var optionsValue = ko.utils.unwrapObservable(obj.optionsValue);
var sourceUrl = ko.utils.unwrapObservable(obj.sourceUrl);
var selectedID = ko.utils.unwrapObservable(allBindings.value);
var model = obj.model;
var unwrapped = ko.utils.unwrapObservable(obj.model);
$(element).select2({
minimumInputLength: 3,
formatResult: function formatResult(result) {
return result.text;
},
data: function (model) {
return { id: unwrapped[optionsValue](), text: unwrapped[optionsText](), data: unwrapped }
},
initSelection: function (element, callback) {
if (unwrapped && selectedID !== "") {
callback({ id: unwrapped[optionsValue](), text: unwrapped[optionsText](), data: unwrapped });
}
},
ajax: {
quietMillis: 500,
url: subdirUrl + sourceUrl,
dataType: 'json',
data: function (search, page) {
return {
page: page,
search: search
};
},
results: function (data) {
var result = [];
$.each(data.list, function (key, value) {
result.push({ id: value[optionsValue], text: value[optionsText], data: value });
});
var more = data.paging.currentPage < data.paging.pageCount;
return { results: result, more: more };
}
}
});
$(element).on('select2-selected', function (eventData) {
if (eventData.choice) {
// item selected
var selectedItem = eventData.choice.data;
var selectedId = eventData.choice.id;
model(selectedItem);
}
else {
model(undefined);
}
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).select2('destroy');
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var obj = valueAccessor(),
allBindings = allBindingsAccessor();
var selectedID = ko.utils.unwrapObservable(allBindings.value);
$(element).val(selectedID).trigger('change');
}
};
It works for url's that dont change, but for urls that need to update, i cant make it work. (it seems like its keeping the first url that was passed (sourceUrl).
Im working with knockout.js and select2 plugin.
Im trying to change the select2 ajax url based on a value of an observable.
for example if based on some selection i do ajax call to 1 url or another.
Here is a sample code:
<input type="hidden" data-bind="bobox: { optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Избери...', sourceUrl: partnerUrl }, value: ApplyToSubject" id="ApplyToSubject" name="ApplyToSubject">
This is how the sourceUrl: partnerUrl is retrieved:
self.partnerUrl = ko.puted(function () {
var value = "";
if (something)
{
value = apiUrls.customer;
}
else if (something else)
{
value = apiUrls.vendor;
}
else if(or another thing)
{
value = apiUrls.employee;
}
return value;
});
I work with custom binding. Here is the code for it:
// documentation http://ivaynberg.github.io/select2/
ko.bindingHandlers.bobox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var obj = valueAccessor(),
allBindings = allBindingsAccessor();
var optionsText = ko.utils.unwrapObservable(obj.optionsText);
var optionsValue = ko.utils.unwrapObservable(obj.optionsValue);
var sourceUrl = ko.utils.unwrapObservable(obj.sourceUrl);
var selectedID = ko.utils.unwrapObservable(allBindings.value);
var model = obj.model;
var unwrapped = ko.utils.unwrapObservable(obj.model);
$(element).select2({
minimumInputLength: 3,
formatResult: function formatResult(result) {
return result.text;
},
data: function (model) {
return { id: unwrapped[optionsValue](), text: unwrapped[optionsText](), data: unwrapped }
},
initSelection: function (element, callback) {
if (unwrapped && selectedID !== "") {
callback({ id: unwrapped[optionsValue](), text: unwrapped[optionsText](), data: unwrapped });
}
},
ajax: {
quietMillis: 500,
url: subdirUrl + sourceUrl,
dataType: 'json',
data: function (search, page) {
return {
page: page,
search: search
};
},
results: function (data) {
var result = [];
$.each(data.list, function (key, value) {
result.push({ id: value[optionsValue], text: value[optionsText], data: value });
});
var more = data.paging.currentPage < data.paging.pageCount;
return { results: result, more: more };
}
}
});
$(element).on('select2-selected', function (eventData) {
if (eventData.choice) {
// item selected
var selectedItem = eventData.choice.data;
var selectedId = eventData.choice.id;
model(selectedItem);
}
else {
model(undefined);
}
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).select2('destroy');
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var obj = valueAccessor(),
allBindings = allBindingsAccessor();
var selectedID = ko.utils.unwrapObservable(allBindings.value);
$(element).val(selectedID).trigger('change');
}
};
It works for url's that dont change, but for urls that need to update, i cant make it work. (it seems like its keeping the first url that was passed (sourceUrl).
Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Aug 25, 2014 at 16:51 trajcetrajce 1,4903 gold badges23 silver badges38 bronze badges 3- ko.puted are only triggered when a change happens to any observable used in the logic in the method. So if none of your something, something else, etc. are observables or puted themselves, it will only ever return one value. – Steen Tøttrup Commented Aug 27, 2014 at 11:03
- In the If statements, the variables are observables, and the ko.puted variable is updated each time the inner value changes. But the custom binding ajax url value, seems like its keeping the initial value – trajce Commented Aug 27, 2014 at 14:05
- You should consider putting it up on jsfiddle. – Steen Tøttrup Commented Aug 27, 2014 at 14:34
1 Answer
Reset to default 5I've finally managed to solve this one.
From what i could read from the select2 documentation,
you should pass string or function to ajax url parameter.
So this is what i've done
I've written a function that returns value of the observable (which is the url):
self.returnUrl = function () {
return self.dynamicUrl();
};
And then i pass that function to my custom binding options:
<input data-bind="bobox: { ... sourceUrl: $data.returnUrl }, value: ApplyToSubject" type="hidden" >
Then the custom binding works the same as in the code in the question, with a small change:
...
ajax: {
url: sourceUrl <- this is the returnUrl function
...
}