Milo TODO example

A TODO app made with Milo.js

HTML

<script src="http://i.mol.im/cc/milo/237/dist/milo.bundle.js"></script>
    <!-- An HTML input managed by a component with a `data` facet -->
    <input ml-bind="[data]:newTodo" />

    <!-- A button with an `events` facet -->
    <button ml-bind="[events]:addBtn">Add</button>
    <h3>To-Do's</h3>

    <!-- Since we have only one list it makes sense to declare
         it like this. To manage multiple lists, a list class
         should be setup like this: ml-bind="MyList:todos" -->
    <ul ml-bind="[list]:todos">

        <!-- A single todo item in the list. Every list requires
             one child with an item facet. This is basically milo's
             ng-repeat, except that we manage lists and items separately
             and you can include any other markup in here that you need. -->
        <li ml-bind="Todo[item]:todo">

            <!-- And each list has the following markup and child
                 components that it manages. -->
            <input ml-bind="[data]:checked" type="checkbox">

            <!-- Notice the `contenteditable`. This works, out-of-the-box
            with `data` facet to fire off changes to the `minder`. -->
            <span ml-bind="[data]:text" contenteditable="true"></span>
            <button ml-bind="[events]:deleteBtn">X</button>

        </li>
    </ul>

    <!-- This component is only to show the contents of the model -->
    <h3>Model</h3>
    <div ml-bind="[data]:modelView"></div>

CSS

/* Style for checked items */
.todo-item-checked {
    color: #888;
    text-decoration: line-through;
}

JavaScript

// Creating a new facetted component class with the `item` facet.
// This would usually be defined in it's own file.
// Note: The item facet will `require` in 
// the `container`, `data` and `dom` facets
var Todo = _.createSubclass(milo.Component, 'Todo');
milo.registry.components.add(Todo);

// Adding our own custom init method
_.extendProto(Todo, { init: Todo$init });

function Todo$init() {
    // Calling the inherited init method.
    milo.Component.prototype.init.apply(this, arguments);
    
    // Listening for `childrenbound` which is fired after binder
    // has finished with all children of this component.
    this.on('childrenbound', function() {
        // We get the scope (the child components live here)
        // It attaches components to DOM elements with ml-bind attribute
        var scope = this.container.scope;

        // And setup two subscriptions, one to the data of the checkbox
        // The subscription syntax allows for context to be passed
        scope.checked.data.on('', { subscriber: checkTodo, context: this });

        // and one to the delete button's `click` event.
        scope.deleteBtn.events.on('click', { subscriber: removeTodo, context: this });
    });

    // When checkbox changes, we'll set the class of the Todo accordingly
    function checkTodo(path, data) {
        this.el.classList.toggle('todo-item-checked', data.newValue);
    }

    // To remove the item, we use the `removeItem` method of the `item` facet
    function removeTodo(eventType, event) {
        this.item.removeItem();
    }
}


// Milo ready function, works like jQuery's ready function.
milo(function() {

    // Call binder on the document.
    var scope = milo.binder();

    // Get access to our components via the scope object
    var todos = scope.todos // Todos list
        , newTodo = scope.newTodo // New todo input
        , addBtn = scope.addBtn // Add button
        , modelView = scope.modelView; // Where we print out model

    // Setup our...