问题
I am working on a SPA that contains multiple areas that I dynamically load into a div (id=#main).
In order to achieve such I use SammyJS for the routing and knockoutjs for the binding. The particular subpage is loaded like $('#main').load('pages/subpage.html'); where the subpage contains two divs that are switched (master/detail pattern).
The data is loaded using .getJSON('data.php',....) into an observableArray within the knockout Model created.
Everything works fine and a list of the items is displayed when loading the page the firsttime.
When I select an Item and switch back to the list using the back-button, which simply invokes self.list() where I set the currentUser to null, instead of the proper list containing the items of the users array it shows the pure mask without any data-bindings regarded (both divs are shown).
The error: The list of items is not displayed anymore although the data is still there (which was checked using console.log(...). The data is definitely available and correct but somehow the binding is not updated ...
Here the particular code-sample:
<div data-bind="load: loadData()">
<div id="userlist" class="row" data-bind="visible: !currentUser()">
<h1 class="lead">Please select a User ...</h1>
<div class="twelve columns">
<table class="striped rounded" data-bind="visible: users().length > 0">
<thead>
<tr>
<th>ID</th>
<th>First name</th>
<th>Last name</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody data-bind="foreach: users">
<tr data-bind="click: $parent.show">
<td><span data-bind="text: id"></span></td>
<td><span data-bind="text: firstname"></span></td>
<td><span data-bind="text: lastname"></span></td>
<td>
<a class="default btn" data-bind="click: $parent.show">show</a>
<a class="default btn" data-bind="click: $parent.delete">delete</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!--
User Details
-->
<div id="userdetails" class="row" data-bind="with: currentUser">
<div class="breadcrumb"><span data-bind="click: $root.list">Userdetails ></span> <span data-bind="text: name"></span></div>
<div class="twelve columns">
<table class="striped rounded">
<tbody>
<form></form>
<tr class="field">
<td><label class="inline" for="userFirstName">Firstname</label></td>
<td style="width:100%"><input class="normal text input" name="userFirstName" type="text" placeholder="First name" data-bind="value: firstname"></td>
</tr>
<tr class="field">
<td><label class="inline" for="userlastname">Firstname</label></td>
<td style="width:100%"><input class="normal text input" name="userlastname" type="text" placeholder="Family name" data-bind="value: lastname"></td>
</tr>
</tbody>
</table>
<div>
<div class="medium btn default"><a href="#" data-bind="click: $root.save">save</a></div>
<span> </span>
<div class="medium btn default"><a href="#" data-bind="click: $root.delete">delete</a></div>
<div class="medium btn default"><a href="#/users">back</a></div>
</div>
</div>
</div>
<!--
Knockout Models
-->
<script>
ko.validation.init({ grouping : { deep: true, observable: true } });
ko.validation.rules.pattern.message = 'Invalid.';
ko.validation.configure({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true,
//messageTemplate: null,
decorateElement: true
});
var userModel = function(){
var self = this;
self.id = ko.observable();
self.firstname = ko.observable().extend({required: { message: 'First name is a required field.' }});
self.lastname = ko.observable().extend({required: { message: 'Last name is a required field.' }});
return self;
};
var userData = function(){
var self = this;
self.users = ko.observableArray([]);
self.currentUser = ko.observable();
self.viewMode = ko.observable('list');
self.list = function(){
self.currentUser(null);
self.viewMode('list');
location.hash = '/users';
console.log('list '+ self.users().length+ ' users');
console.log(ko.toJSON(self.users()));
};
self.show = function(item){
self.currentUser(item);
self.viewMode('details');
location.hash = '/users/' + item.id();
console.log('show user:'+ko.toJSON(item));
};
self.loadData = function(){
//fetch existing data from database
console.log('loaddata - User');
//self.users = ko.observableArray([]);
$.getJSON("pages/user.php", function(data) {
data.forEach(function(item){
var newModel = new userModel();
newModel.id(item['id']);
newModel.firstname(item['firstname']);
newModel.lastname(item['lastname']);
self.users.push(newModel);
});
});
}
}
if (!_userData){
var _userData = new userData();
ko.applyBindings(_userData);
}
</script>
来源:https://stackoverflow.com/questions/19319021/knockout-js-data-binding-not-updated