Knockout conditional observable

by David Kyle

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.2.1.debug.js"></script>
<div id="list-wrapper">
    <div class="list-div">
        <h2 class="header">Input</h2>
        <h4 class="sub-header">Change</h4>
        <select data-bind="foreach: List">
        </select>
        <h4 class="sub-header">New</h4>
        <fieldset>
            <legend>Add new List Item</legend>
            <label for="id-input">ID:</label>
            <input type="text" name="id-input" id="id-input" />
            <br />
            <label for="name-input">Name:</label>
            <input type="text" name="name-input" id="name-input" />
            <br />
            <input type="button" name="add-button" id="add-button" value="Add" />
        </fieldset>
    </div>
    <div class="list-div" data-bind="data: List">
        <h2 class="header">Output</h2>
        <ul data-bind="foreach: Items">
            <li><span data-bind="text: Name"></span></li>
        </ul>
     </div>
</div>

CSS

.list-div
{
    margin: 10px auto;
    width: 80%;
    border: solid 1px #000000;
    border-radius: 8px;
    padding: 4px;
    text-align: left;
    font-family: Verdana, Arial, Sans-Serif;
    color: #232323;
    background-color: #efefef;
    height: 200px;
}
.header {
    text-align: center;
    text-shadow: 0px 2px 3px #ababab;
    margin: 0px auto;
    width: 100%;
    display: block;
    margin-bottom: 0px;
    border-bottom: solid 1px #ababab;
}
.sub-header {
    text-align: left;
    margin-left: 10px;
    display: block;
    width: 20%;
    background-color: #dedede;
    border-bottom: solid 1px #bcbcbc;
    margin-bottom: 4px;
    margin-top: 4px;
}
SELECT
{
    margin-left: 15px;
}
FIELDSET {
    margin-left: 10px;
}
LEGEND {
    margin-left: 20px;
}
LABEL {
    width: 60px;
    display: inline-block;
    text-align: right;
}
#id-input {
    width: 40px;
    border-radius: 5px;
    border-width: 1px;
}
#name-input {
    width: 80px;
    border-radius: 5px;
    border-width: 1px;
}
INPUT[type="button"] {
    padding: 1px 3px;
}
INPUT[type="text"] {
    margin: 2px 0px;
}

JavaScript

$(document).ready(function() {
    $("#add-button").bind("click", function(e) {
        var newId = "";
        var newName = "";
        newId = $("#id-input").val();
        newName = $("#name-input").val();
        $("#id-input").val("");
        $("#name-input").val("");
        viewModel.List.AddItem({ID: newId, Name: newName});
    });
});


var RootViewModel = function() {
     var self = this;
    self.List = new ListViewModel();
};

var ListViewModel = function() {
    var self = this;
    self.Items = ko.observableArray([]);
    
    self.GetItemById = function(id) {
        if (self.Items().length > 0) {
            var localItems = self.Items();
            for(var i =0;i<localItems.length;i++) {
                if (localItems[i].ID() == id) {
                    return localItems[i];
                } // end if
            } // end for loop
        } // end if
    };
    
    self.AddItem = function (plainItem) {
      var localItems = self.Items;
      var newItem = new ListItemViewModel();
        newItem.ID(plainItem.ID);
        newItem.Name(plainItem.Name);
        localItems.push(newItem);
        self.Items.valueHasMutated();
    };
};

var ListItemViewModel = function() {
    var self = this;
    self.ID = ko.observable("");
    self.Name = ko.observable("");
};

var viewModel = new RootViewModel();
ko.applyBindings(viewModel);