问题
I have a observable defined inside a object literal of a knockout viewmodel . Now when I ran the application .Its unable to access the observable .
$(function () {
var viewModel = {
Folders: ['Inbox', 'Archive', 'Sent', 'Spam'],
Title: ko.observable("My View Model Test"),
SelectedFolder: ko.observable(),
Mails: ko.observableArray(),
SelectedMail: ko.observable(),
SelectedChoices: ko.observable(false),
navigate: function (folder) {
SelectedFolder(folder);
$.ajax({
url: "/Api/MailBox",
data: { folder: folder },
success: function (data) {
self.Mails(data);
},
statusCode: {
404: function () {
console.log("No Mails");
}
}
});
}
};
}
when I have bind the click event to navigate
function . It says SelectedFolder
is undefined . Can someone tell me why is it unable to access the SelectedFolder
observable inside the navigate
function ?
回答1:
When the navigate method is running and it looks for the SelectedFolder observable, it first looks for it in the context of the navigate method. Failing that, it jumps up to the parent context, which is the anonymous function being run when the page is ready. Failing that, it jumps to the global context - it can't find SelectedFolder there, so it then gives up.
To fix this, change your navigate method to reference the viewModel variable that is available in the context of the anonymous function being run when the page is ready:
navigate: function (folder) {
viewModel.SelectedFolder(folder);
$.ajax({
url: "/Api/MailBox",
data: { folder: folder },
success: function (data) {
viewModel.Mails(data);
},
...
Note that I also added a reference to the viewModel in the success callback so that it could find the Mails observable.
This should work, however, I would recommend considering changing your structure so that your navigate method isn't dependent on specific global variables. Here is one way:
var myViewModel = function() {
var self = this;
self.Folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
self.Title = ko.observable("My View Model Test");
self.SelectedFolder = ko.observable();
self.Mails = ko.observableArray();
self.SelectedMail = ko.observable();
self.SelectedChoices = ko.observable(false);
self.navigate = function (folder) {
self.SelectedFolder(folder);
$.ajax({
url: "/Api/MailBox",
data: { folder: folder },
success: function (data) {
self.Mails(data);
},
statusCode: {
404: function () {
console.log("No Mails");
}
}
});
};
};
$(function () {
var ViewModel = new myViewModel();
ko.applyBindings(viewModel);
});
回答2:
The issue is probably what the current context is when the method is called. If the method is being called by a click event then this
is probably the object which the click event was bound to, and so it tries to find a SelectedFolder method on that element.
Not sure if this is the best way, but here is one possible solution:
var viewModel = {
Folders: ['Inbox', 'Archive', 'Sent', 'Spam'],
Title: ko.observable("My View Model Test"),
SelectedFolder: ko.observable(),
Mails: ko.observableArray(),
SelectedMail: ko.observable(),
SelectedChoices: ko.observable(false)
};
viewModel.navigate = function (folder) {
viewModel.SelectedFolder(folder);
$.ajax({
url: "/Api/MailBox",
data: { folder: folder },
success: function (data) {
viewModel.Mails(data);
},
statusCode: {
404: function () {
console.log("No Mails");
}
}
});
来源:https://stackoverflow.com/questions/13992298/observable-not-defined-inside-object-literal-knockout