Reputation: 3761
I've got the following js:
var ViewModel = function() {
var self = this;
self.projects = ko.observableArray([]);
self.currentProject = ko.observable();
self.selectProject = function (project) {
self.currentProject(project);
};
}
var vm = new ViewModel();
ko.applyBindings(vm);
$(function() {
$('#spinner-wrapper').show();
$.getJSON("some/url", function(data){
vm.projects(data.projects);
vm.selectProject(data.projects[0]);
});
});
And the following HTML:
<ul class="nav nav-pills nav-stacked" data-bind="foreach: {data:projects, as: 'project'}">
<li><a href="#" data-bind="text:projectName, click: vm.selectProject"></a></li>
</ul>
<h1 data-bind="text:currentProject.projectName"></h1>
So everytime I click an <a>
, the selectProject
method get called, and self.currentProject
changes properly. The problem I have is that h1
doesn't show anything.
Upvotes: 1
Views: 1602
Reputation: 23372
Your currentProject
property is observable. This means it's a function you'll have to call to get your actual property from it. The function doesn't have a property named pojectName
, so it will return undefined
(note that it won't throw an error).
If you can be sure currentProject
always holds an object with a projectName
property, you can easily fix your data-bind like so:
data-bind="currentProject().projectName"
(Find out how knockout gets and sets observables here)
However, in your view model, currentProject
is initialized with value undefined
. Here's some ways of dealing with the undefined value:
with
binding (my personal preference)A with
binding doesn't render nor data-binds the HTML it encapsulates if its value isn't properly defined:
<h1 data-bind="with: currentProject">
<span data-bind="text: projectName"></span>
</h1>
Drawbacks: you'll need an extra element or a virtual binding. Watch out that there aren't any weird flashes when elements are removed...
Create a computed property in your viewmodel:
self.currentProjectName = ko.pureComputed(function() {
var currentProject = self.currentProject();
return currentProject ? currentProject.projectName : "";
});
Drawbacks: clutters your view model. Pros: easily create an empty state/placeholder
Fix it in the data-bind:
<h1 data-bind="text:currentProject() ? currentProject().projectName : ''"></h1>
This is basically the same approach as (2).
Drawbacks: clutters your view, prone to bugs.
Upvotes: 1