How to use Knockout JS Array Map to make select option binding default to default value based on input condition?
asynchronous
I use Computed Observable
and bind data to select options Array Map
.
Using the following code structure, how can I set the "Country" as the default value in the select option? For example: if the user is from, Albania
set the default country to Albania
. Note that I am using and need to use the selected value as an argument to another function.
Complete code:
(function(){
var self = this;
self.SelectedCountry = ko.observableArray([]);
self.CountryData = ko.observableArray([]);
$.getJSON('https://restcountries.eu/rest/v1/all', function(data){
self.CountryData(data);
});
function viewModel(){
// Add some possible logic to make country default based on input
// from user. E.g. If data.alpha3Code === '1234'
self.Countries = ko.computed(function () {
return ko.utils.arrayMap(CountryData(),
function (data) {
return {
Name: data.name + ' ' + data.capital,
value: data.alpha3Code
}
});
}).extend({notify: 'always'})
}
self.Location = ko.computed(function () {
if (self.SelectedCountry()) {
return ko.utils.arrayFilter(CountryData(), function (item) {
return item.alpha3Code === self.SelectedCountry().value;
});
}
});
ko.applyBindings(new viewModel());
})();
Roy
Your code has many problems here.
SelectedCountry
should be an observable, not an observableArray- viewModel is not the correct constructor and should not be used
new
(I got rid of it completely) - you should pass
self
toapplyBindings
- You may want to
optionsValue: 'value'
choose binding self
Should be initialized to an empty object.this
is the global object where you complete the action. You probably meant to wrap it all in the constructor.- You need to be
self
at the top of theCountryData
calculation . - position should only return names, not arrays, because if
SelectedCountry
undefined, there is no array and[0]
will break
Forget all of that, you just need to set the value SelectedCountry
and the selection will update accordingly. The only trick is that you need valueAllowUnset: true
to add another binding to the select to tell it that the value you select may not exist (at least not until the data is loaded).
(function() {
var self = {};
self.SelectedCountry = ko.observable('BHR');
self.CountryData = ko.observableArray([]);
$.getJSON('https://restcountries.eu/rest/v1/all', function(data) {
self.CountryData(data);
});
self.Countries = ko.computed(function() {
return ko.utils.arrayMap(self.CountryData(),
function(data) {
return {
Name: data.name + ' ' + data.capital,
value: data.alpha3Code
}
});
}).extend({
notify: 'always'
})
self.Location = ko.computed(function() {
if (self.SelectedCountry()) {
var match = ko.utils.arrayFilter(self.CountryData(), function(item) {
return item.alpha3Code === self.SelectedCountry();
})[0];
if (match) {
return match.name;
}
}
});
ko.applyBindings(self);
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: Countries, optionsText: 'Name', optionsValue: 'value', valueAllowUnset: true, value: SelectedCountry"></select>
<p>Welcome! You are from:</p> <span data-bind="text: Location()"></span>