问题
I am combining an Options binding and a Computed, and am getting the error in the Firebug console:
TypeError: this.selectedCountryNeverNull is undefined
This is the relevant part of the ViewModel:
// Constructor for an object with two properties
var Country = function (name, population) {
this.countryName = name;
this.countryPopulation = population;
};
var viewModel = {
availableCountries: ko.observableArray([
new Country("UK", 65000000),
new Country("USA", 320000000),
new Country("Sweden", 29000000)
]),
selectedCountry: ko.observable(), // Nothing selected by default
selectedCountryNeverNull: ko.observable(), // has default
selectedCountryDesc: ko.computed(function () { return '*' + this.selectedCountryNeverNull.countryName + '*'; }, this)
};
and this is the select:
<select data-bind="options: availableCountries,
optionsText: 'countryName',
value: selectedCountryNeverNull"></select>
I left out the optionsCaption:
so that the first array element is the default, and the value is never null.
Firebug says the error is in the ko.computed
line, and I tried to add ()
parentheses here and there, but with no avail.
I want to do much bigger ko.computed
stuff, but isolated my problem in this extension of an example from the knockout site.
Thanks for any help in trying to understand the parentheses issues in general and mine particular.
回答1:
I see three problems with your code:
this
in yourko.computed
refers toWindow
, not toviewModel
,- The
select
binding sets its value at the time ofapplyBindings
, so for a brief period of time,selectedCountryNeverNull
is actually undefined. This means you'll have to set it with a default manually or check for falsey values in your comptued - In the computed, you'll need to use the
()
to getselectedCountryNeverNull
's value and create a dependency.
An example on how to fix all three:
- Use a constructor and the
new
keyword to managethis
, - Default to an empty object in the computed (
|| {}
) - Call the observable in the computed (
()
)
// Constructor for an object with two properties
var Country = function(name, population) {
this.countryName = name;
this.countryPopulation = population;
};
var ViewModel = function() {
this.availableCountries = ko.observableArray([
new Country("UK", 65000000),
new Country("USA", 320000000),
new Country("Sweden", 29000000)
]);
this.selectedCountry = ko.observable(); // Nothing selected by default
this.selectedCountryNeverNull = ko.observable(); // has default
this.selectedCountryDesc = ko.computed(function() {
return '*' + (this.selectedCountryNeverNull() || {}).countryName + '*';
}, this);
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: availableCountries,
optionsText: 'countryName',
value: selectedCountryNeverNull"></select>
Selection: <span data-bind="text: selectedCountryDesc"></span>
来源:https://stackoverflow.com/questions/42394966/where-should-i-use-parentheses-with-knockout-computed-and-arrays