<!-- Folders -->
<!-- Mails grid -->
<table class="mails" data-bind="with: chosenFolderData">
<thead>
<tr>
<th>
<select data-bind="foreach: folders">
<option data-bind="text: $data,
css: { selected: $data == $root.chosenFolderId() },
click: $root.goToFolder"></option>
</select>
</th>
<th>To</th><th>Subject</th><th>Date</th></tr></thead>
<tbody data-bind="foreach: mails">
<tr>
<td data-bind="text: from"></td>
<td data-bind="text: to"></td>
<td data-bind="text: subject"></td>
<td data-bind="text: date"></td>
</tr>
</tbody>
</table>
function WebmailViewModel() {
// Data
var self = this;
self.folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
self.chosenFolderId = ko.observable();
self.chosenFolderData = ko.observable();
// Behaviours
self.goToFolder = function(folder) {
self.chosenFolderId(folder);
$.get('/mail', { folder: folder }, self.chosenFolderData);
};
// Show inbox by default
self.chosenFolderData({folders:['Inbox', 'Archive', 'Sent', 'Spam']});
};
ko.applyBindings(new WebmailViewModel());
<select data-bind="options: folders, selectedOption: choosenFolderData"></select>
<select data-bind="options: folders, selectedOption: $parent.choosenFolderData"></select>
<table class="mails">
<thead>
<tr>
<th>
<select data-bind="options: folders, value: chosenFolderId"></select>
</th>
<th>To</th><th>Subject</th><th>Date</th></tr></thead>
<tbody data-bind="with: chosenFolderData">
<!-- ko foreach: mails -->
<tr>
<td data-bind="text: from"></td>
<td data-bind="text: to"></td>
<td data-bind="text: subject"></td>
<td data-bind="text: date"></td>
</tr>
<!-- /ko -->
</tbody>
</table>
function WebmailViewModel() {
// Data
var self = this;
self.folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
self.chosenFolderId = ko.observable();
self.chosenFolderData = ko.observable();
// Behaviours
// Subscribe to chosenFolderId and fetch new data when it changes
self.chosenFolderId.subscribe(function(id) {
$.get('/mail', { folder: id }, ...); // update chosenFolderData });
// Show inbox by default, and kickoff initial fetch
self.chosenFolderId('Inbox');
};
ko.applyBindings(new WebmailViewModel());
Only use the with binding in places where changing the context actually simplifies the code. In this case, that is only the table body. Using it on the entire table means having to escape the select bindings to the root for no good reason.
Using the options binding with value specified means that the chosenFolderId observable will be kept up to date. It is then possible to subscribe to changes in that observable in order to trigger the fetch request for new data from the server.