JSFiddle - React, Tailwind, and code Playground

by rpallas

HTML

<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.1.0rc2.debug.js"></script>
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
<script src="https://github.com/downloads/ericmbarnard/Knockout-Validation/knockout.validation.v0.9.js"></script>
<fieldset class="control-group">
    
    Name: <input type="text" data-bind="value: name, valueUpdate: 'afterkeydown'" />
    <input type="checkbox" data-bind="checked: nameVisible" />
    <p>
        Hello, <span data-bind="text: name, visible: nameVisible"></span>
        <br/>
        <span data-bind="text: displayName"></span>
    </p>
    <button class="btn btn-primary" data-bind="click: changeName">Change name</button>
    <br/>
    <button class="btn btn-success btn-small" data-bind="click: addItem">Add</button>
    <button class="btn btn-danger btn-small" data-bind="click: removeItem">Remove</button>
    
    <ul data-bind="template: { name: 'listTemplate', foreach: list }">
    </ul>

</fieldset>

<!-- ======= Templates ======= -->

<script id="listTemplate" type="text/html">
    <li data-bind="text: name"></li>
</script>

CSS

body {margin: 15px;}
.btn {margin: 2px;}

JavaScript

ko.validation.rules.pattern.message = 'Invalid.';
    
ko.validation.configure({
    registerExtenders: true,
    messagesOnModified: true,
    insertMessages: true,
    parseInputAttributes: true,
    messageTemplate: null
});

$(function() {
    var data = [{name: "Robbie"},{name: "Phil"},{name: "Matt"}];

    var viewModel = {
        name: ko.observable("").extend({ minLength: 2 }),
        changeName: function() {
            this.name("Phil");
        },
        nameVisible: ko.observable(true),
        list: ko.observableArray(data),
        addItem: function() {
            if(viewModel.errors().length == 0)
            {
                this.list.push({
                    name: this.name()
                });
            }else{
                viewModel.errors.showAllMessages();
            }
        },
        removeItem: function() {
            this.list.pop();
        }
    };

    viewModel.errors = ko.validation.group(viewModel);
    
    viewModel.displayName = ko.computed(function() {
        return this.name() + " is" + (!this.nameVisible() ? " not" : "") + " visible.";
    }, viewModel);

    ko.applyBindings(viewModel);
});