Knockout master-detail

by smichelotti

HTML

<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-1.3.0beta.debug.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/redmond/jquery-ui.css">
<div class="master ui-widget-content ui-corner-all">
    <h3 class="title ui-widget-header">Tags</h3>
    <input id="newTag" type="text" placeholder="Add New Tag" data-bind="value: itemToAdd, valueUpdate: 'afterkeydown', event: { keypress: checkAdd }" />
    <button type="submit" data-bind="click: addTag">Add</button>
    
    <table>
        <tbody data-bind='template: {name:"tagsTemplate", foreach:tags}'></tbody>
    </table>
    
    <script type="text/html" id="tagsTemplate">
        <tr>
            <td><span data-bind="text: Name"/></td>
            <td><button class="edit-item">Edit</button></td>
            <td><button class="remove-item">Remove</button></td>
            <td><button class="drills">Drills</button></td>
        </tr>
    </script>
</div>
<div class="detail ui-widget-content ui-corner-all">
    <h3 class="title ui-widget-header">Drills</h3>
    <table>
        <tr>
            <th>Name</th>
            <th>Description</th>
        </tr>
        <tbody data-bind='template: {name:"drillsTemplate", foreach:currentTagDrills}'></tbody>
    </table>
    <script type="text/hml" id="drillsTemplate">
        <tr>
            <td><span data-bind="text: Name"/></td>        
            <td><span data-bind="text: Description"/></td>        
        </tr>
    </script>
</div>

<div id="tagDialog" />

JavaScript

$(function() {
    var viewModel = {
        // Data
        itemToAdd: ko.observable(""),
        tags: ko.observableArray(fakeData.Tags),
        selectedTag: ko.observable(fakeData.Tags[1]),
        currentTagDrills: ko.observableArray([]),
        
        // Behaviors
        selectTag: function(tag) {
            this.selectedTag(tag);
        },

        addTag: function() {
            this.tags.push({
                Name: this.itemToAdd()
            });
            this.itemToAdd("");
        },

        checkAdd: function(event) {
            if (event.charCode === 13) {
                this.addTag();
                return false;
            }
            return true;
        }
    }; // end viewModel

    var tagDialog = $("#tagDialog").dialog({
        autoOpen: false
    });
    
    $(".remove-item").live("click", function() {
        viewModel.tags.remove(ko.dataFor(this));
    });

    $(".edit-item").live("click", function() {
        tagDialog.dialog("open");
    });
    
    $(".drills").live("click", function() {
        console.log("in drills click");
        viewModel.selectTag(ko.dataFor(this));
    });
    
    ko.applyBindings(viewModel);

    ko.dependentObservable(function() {
        console.log("in dep observable: ");
        console.log(this.selectedTag().Name);
        this.currentTagDrills(fakeData[this.selectedTag().Name]);
    }, viewModel);
});







//Fake data for jsFiddle echo AJAX requests
var fakeData = {};

fakeData.Tags = [{
    "Id": 1,
    "Name": "Transition"},
{
    "Id": 2,
    "Name": "Passing"},
{
    "Id": 3,
    "Name": "Ball Handling"},
{
    "Id": 4,
    "Name": "Shooting"},
{
    "Id": 5,
    "Name": "Team Offense"},
{
    "Id": 6,
    "Name": "Team Defense"},
{
    "Id": 7,
    "Name": "Rebounding"},
{
    "Id": 8,
    "Name": "Defense"}];

fakeData.Transition = [{
    "Id": 2,
    "Name": "Perfection",
    "Description": null,
    "TagId": 2,
    "Tag": null},
{
    "Id": 3,
    "Name": "3-man Weave",
  ...