JSFiddle - React, Tailwind, and code Playground

by amitava82

HTML

<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-latest.debug.js"></script>
<p>
    issue: When the select options are read, the inital value gets reset to the first object in the options. How do I keep the original value selected when transitioning to edit mode?
</p>

<div>
    <h2>Edit Quote '1001'</h2>
    
    <div class="editor-row" data-bind="with: selectedCustomer">
        <label>Customer</label>
        <div data-bind="visible: !$root.isEditMode()">
            <span data-bind="text: CompanyName"></span>
        </div>
        <div data-bind="visible: $root.isEditMode()">
            <input type="radio" name="customerGroup" value="1" data-bind="checked: id"> Company Name 1
            <input type="radio" name="customerGroup" value="2" data-bind="checked: id"> Company Name 2
        </div>
    </div>

    <div class="editor-row">
        <label>Project</label>
        <div data-bind="visible: !isEditMode()">
            <span data-bind="text: selectedProject().Name"></span>
        </div>
        <div data-bind="visible: isEditMode()">
            <select data-bind="options: selectedCustomer().projects, optionsText: 'Name', value: selectedProject"></select>
        </div>
    </div>

    <div>
        <button data-bind="click: function() { turnOnEditMode() }">Edit</button>
        <button data-bind="click: function() { turnOffEditMode() }">Cancel</button>
    </div>
</div>

<hr/>

<div data-bind="text: ko.toJSON($root)"></div>

<!-- inital values from server -->
<div id="customerData" data-id="1" data-companyName="Company Name 1"></div>
<div id="projectData" data-id="13" data-name="project 13"></div>

CSS

h2 { padding:.5em; text-align:center; font-weight:bold; }

.editor-row
{
    clear: right;
    padding: 1em;
}

.editor-row label 
{
    display: block;
    clear: right;
}

JavaScript

function ajaxCallGetProjectsByCustomer(customerId) {
    var database = '[{"CustomerId": 1, "Name":"Company Name 1", "Projects": [ { "ProjectId": "11", "Name": "project 11" }, { "ProjectId": "12", "Name": "project 12" }, { "ProjectId": "13", "Name": "project 13" }] }, {"CustomerId": 2, "Name": "Company Name 2", "Projects": [ { "ProjectId": "21", "Name": "project 21" }, { "ProjectId": "22", "Name": "project 22" }, { "ProjectId": "23", "Name": "project 23" }] }]';
    
    var json = ko.utils.parseJson(database);
    //console.log('parseJson(database) - ' + json);
    
    //ko.utils.arrayForEach(json, function(item) {
    //    console.log('CustomerId: ' + item.CustomerId);
    //});
    
    return ko.utils.arrayFirst(json, function(item){
        return item.CustomerId == customerId;
    });
}

var Customer = function(id, name, projects) {
    var self = this;
    
    this.id = ko.observable(id);
    this.CompanyName = ko.observable(name);
    
    this.projects = ko.observableArray(ko.utils.arrayMap(projects, function(item) {
        return new Project(item.ProjectId, item.Name);
    }));
    
    this.id.subscribe(function(){
        Customer.load(Number(this.id()));
    }, this);
};

Customer.load = function(id) {
    var data =  ajaxCallGetProjectsByCustomer(id);

    var customer = new Customer(
        data.CustomerId, 
        data.Name, 
        data.Projects);
    
    var oldProjectId = viewModel.selectedProject().id;
    viewModel.selectedCustomer(customer);
    //******* HERE IS THE MAIN ISSUE *******
    // the viewModel.selectedProject instance has been destroyed
    // by loading a new customer instance so even though project id 3 may
    // be in selectedProject its not the **same** project with id 3 that is in the
    // new customer so hence the binding equality comparer fails and it is ignored
    // by reselecting the correct istance this can be fixed although it is a hack
    
    var sameProjectDifferentInstance =...