问题
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