JSFiddle - React, Tailwind, and code Playground

by OlsonDev

HTML

<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.debug.js"></script>
<p id="instructions">
    <strong>Instructions:</strong> Note the select shows "foo1". Note the "changelog" output; immediately something looks wrong. bar1's <code>fooId</code> changed twice. Initially its value was 1. Then a <code>change</code> event was fired, which changed its value to an empty string. If you click bar2, you'll see bar2's <code>fooId</code> value change to an empty string. However, the select will display "foo2". Switch back to bar1. The select now is updated to reflect the (erroneously updated) model. Click bar2; you'll see the same change.
</p>

<div data-bind="foreach: bars">
    <button type="button" data-bind="click: $root.setActiveBar, text: name(), css: { active: $data == $root.activeBar() }"></button>
</div>

<div data-bind="with: activeBar">
    <select data-bind="value: fooId">
        <option value="">-- Select a foo --</option>
        <!-- ko foreach: $root.foos -->
            <option data-bind="value: id, text: name"></option>
        <!-- /ko -->
    </select>
</div>

<textarea id="changelog"></textarea>

CSS

button {
    color: #888;
    background-color: #DDD;
    border: 1px solid #ABADB3;
    border-radius: 2px;
    font-size: 16px;
    padding: 5px 20px;
}
button:hover {
    color: #666;
}
button.active {
    color: #000;
}
#changelog {
    display: block;
    width: 300px;
    height: 300px;
}
#instructions {
    font-family: sans-serif;
    margin: 5px;
    max-width: 500px;
}
strong {
    font-weight: bold;
}

JavaScript

function Foo(id, name) {
    var self = this;
    self.id = ko.observable(id);
    self.name = ko.observable(name);
}

function Bar(id, name, fooId) {
    var self = this;
    self.id = ko.observable(id);
    self.name = ko.observable(name);
    self.fooId = ko.observable(null);        
    self.fooId.subscribe(function(newFooId) {
        $('#changelog').append(self.name() + ".fooId changed to: " + newFooId + '\n');
    });
    self.fooId(fooId);
}

function ViewModel() {
    var self = this;
    self.foos = ko.observableArray([]);
    self.foos.push(new Foo(1, 'foo1'));
    self.foos.push(new Foo(2, 'foo2'));

    self.bars = ko.observableArray([]);
    self.bars.push(new Bar(1, 'bar1', 1));
    self.bars.push(new Bar(2, 'bar2', 2));    
    self.bars.push(new Bar(2, 'bar3', 1));
    self.bars.push(new Bar(2, 'bar4', 2));
    self.activeBar = ko.observable(self.bars()[0]);
    
    self.setActiveBar = function(bar) {
        self.activeBar(bar);
    };
}

ko.applyBindings(window.vm = new ViewModel());