JSFiddle - React, Tailwind, and code Playground

by meetravi

HTML

<script src="learn.knockoutjs.com/Scripts/Lib/knockout-1.3.0.latest.js"></script>
<script src="http://learn.knockoutjs.com/Scripts/Lib/jquery.tmpl.js"></script>
<h2>Contacts</h2>
<div id="contactsList" data-bind='template: "contactsListTemplate"'> </div>
<script type="text/html" id="contactsListTemplate">
    <table class='contactsEditor'>
        <tr>
            <th>First name</th>
            <th>Last name</th>
            <th>Phone numbers</th>
        </tr>
        {{each(i, contact) contacts()}}                   
            <tr>
                <td>
                    <input data-bind="value: firstName" />
                    <div><a href="#" data-bind="click: function() { viewModel.removeContact(contact) }">Delete</a></div>
                </td>
                <td><input data-bind="value: lastName" /></td>
                <td>
                    <table>
                        {{each(i, phone) phones}}
                            <tr>
                                <td><input data-bind="value: type" /></td>
                                <td><input data-bind="value: number" /></td>
                                <td><a href="#" data-bind="click: function() { viewModel.removePhone(contact, phone) }">Delete</a></td>
                            </tr>
                        {{/each}}
                    </table>
                    <a href="#" data-bind="click: function() { viewModel.addPhone(contact) }">Add number</a>
                </td>
            </tr>
        {{/each}}
    </table>
</script>
 
<p>
    <button data-bind="click: addContact">Add a contact</button>
    <button data-bind="click: save, enable: contacts().length > 0">Save to JSON</button>
</p>
 
<textarea data-bind="value: lastSavedJson" rows="5" cols="60" disabled="disabled"> </textarea>

JavaScript

var viewModel = {
    contacts: new ko.observableArray([
        { firstName: "Danny", lastName: "LaRusso", phones: [
            { type: "Mobile", number: "(555) 121-2121" },
            { type: "Home", number: "(555) 123-4567"}]
        },
        { firstName: "Sensei", lastName: "Miyagi", phones: [
            { type: "Mobile", number: "(555) 444-2222" },
            { type: "Home", number: "(555) 999-1212"}]
        }
    ]),
    addContact: function () {
        viewModel.contacts.push({ firstName: "", lastName: "", phones: [] });
    },
    removeContact: function (contact) {
        viewModel.contacts.remove(contact);
    },
    addPhone: function (contact) {
        contact.phones.push({ type: "", number: "" });
        viewModel.contacts.valueHasMutated();
    },
    removePhone: function (contact, phone) {
        ko.utils.arrayRemoveItem(contact.phones, phone);
        viewModel.contacts.valueHasMutated();
    },
    save: function () {
        viewModel.lastSavedJson(JSON.stringify(viewModel.contacts(), null, 2));
    },
    lastSavedJson: new ko.observable("")
};
 
ko.applyBindings(viewModel);