JSFiddle - React, Tailwind, and code Playground

by lamarant

HTML

<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js"></script>
<script src="//cdn.iamwebdeveloper.in/js/knockout.mapping/2.3.2/knockout.mapping.js"></script>
Solution #1 to: <a href="http://stackoverflow.com/questions/16137887" target="_blank">http://stackoverflow.com/questions/16137887</a>
<hr />
<h1>All Foo's</h1>
<div data-bind="template: { name: 'MyTemplate', data: {arr: Foo} }"></div>
<hr />
<h1>All Poo's</h1>
<div data-bind="template: { name: 'MyTemplate', data: {arr: Poo} }"></div>
<hr />

<script type="text/html" id="MyTemplate">
    <div class="addnew">
        Add Member &raquo; 
        <select data-bind="options: $data.arr.listMembers, optionsText: 'ID', optionsValue: 'ID'"></select>
        <button data-bind="click: function() { $root.addMember($data.arr, $element); }">+</button>
    </div>
    <div data-bind="{ foreach: $data.arr }">
        <div>
            Member #<span data-bind="text: ID"></span> &raquo;
            <input type="text" data-bind="value: Title, valueUpdate:'afterkeydown'" />
            <button data-bind="click: function() { $root.removeMember($parent.arr, $data) }">x</button>
        </div>
    </div>
</script>
<h1 class="Debug">Debug</h1>
<strong>viewModel._AllObjects</strong>
<pre data-bind="text: ko.toJSON($data._AllObjects, null, 2)"></pre>
<strong>model.Foo</strong>
<pre data-bind="text: ko.toJSON($data.Foo, null, 2)"></pre>
<strong>model.Poo</strong>
<pre data-bind="text: ko.toJSON($data.Poo, null, 2)"></pre>

CSS

body{color: #444; font-family: Arial; font-size: 14px;}
input{width: 50%; padding: 5px;}
button{cursor: pointer;}
select{padding: 5px;}
h1{font-size: 16px;}
h1.Debug{font-size: 14px; background: red; color: #fff;padding: 5px;}
pre, strong{font-size: 12px;}
.addnew{background: #eee;padding: 5px;margin-bottom: 10px;}

JavaScript

var Members = ko.mapping.fromJS([
    { ID: 100, Title: 'This is item number 100' },
    { ID: 776, Title: 'This is item number 776' },
    { ID: 456, Title: 'This is item number 456' },
    { ID: 999, Title: 'This is item number 999' }
]);

var model = ko.mapping.fromJS({
    AllMembers : Members,    //make Members accessible via $root in data-bind
    Foo : [
        Members()[1]
    ],
    Poo : [
        Members()[1],
        Members()[2]        
    ],
    addMember: function(arrCtx, elem) {        
        var selID = $(elem).parent().find('select').val();  
        if (selID) {
            $.each(model.AllMembers(), function (k, item) {                
                if (item.ID() == selID) {
                    // add the item to ArrCtx by reference
                    arrCtx.push(item);
                }
            });
        }  
    },
    removeMember: function(arrCtx, item) {
        arrCtx.remove(item);
    }
});

arrayInverseIntersect = function(a, b)
{
    return $.grep(a, function(i)
    {
        return $.inArray(i, b) === -1;
    });
};

//methods used for building select boxes
model.Foo.listMembers = ko.computed(function(){
    return arrayInverseIntersect(model.AllMembers(), model.Foo());
});
model.Poo.listMembers = ko.computed(function(){
    return arrayInverseIntersect(model.AllMembers(), model.Poo());
});

ko.applyBindings(model);