WildflowerJS Demos
Todo List: data-list, data-model, data-action, computed

Todos

HTML

<div data-component="todo-list">
    <input type="text" data-model="newTodo"
           data-action="keyup:handleKeyup"
           placeholder="What needs to be done?">
    <button data-action="addTodo">Add</button>

    <button data-action="setFilter" data-filter="all"
            data-bind-class="filter === 'all' ? 'active' : ''">All</button>
    <button data-action="setFilter" data-filter="active"
            data-bind-class="filter === 'active' ? 'active' : ''">Active</button>
    <button data-action="setFilter" data-filter="completed"
            data-bind-class="filter === 'completed' ? 'active' : ''">Completed</button>

    <ul data-list="filteredTodos">
        <template>
            <li>
                <input type="checkbox"
                       data-bind-attr="{ checked: completed }"
                       data-action="change:toggleTodo">
                <span data-bind="text"
                      data-bind-class="completed ? 'completed' : ''"></span>
                <button data-action="removeTodo">&times;</button>
            </li>
        </template>
    </ul>

    <span data-bind="activeCount"></span> items left
    <button data-action="clearCompleted"
            data-show="hasCompleted">Clear completed</button>
</div>

JavaScript

wildflower.component('todo-list', {
    state: {
        newTodo: '',
        filter: 'all',
        todos: [
            { id: 1, text: 'Learn WildflowerJS', completed: true },
            { id: 2, text: 'Build an app', completed: false },
            { id: 3, text: 'Ship it!', completed: false }
        ]
    },
    computed: {
        filteredTodos() {
            if (this.filter === 'active') return this.todos.filter(t => !t.completed);
            if (this.filter === 'completed') return this.todos.filter(t => t.completed);
            return this.todos;
        },
        activeCount() { return this.todos.filter(t => !t.completed).length; },
        hasCompleted() { return this.todos.some(t => t.completed); }
    },
    handleKeyup(event) {
        if (event.key === 'Enter') this.addTodo();
    },
    addTodo() {
        const text = this.newTodo.trim();
        if (text) {
            this.todos.push({ id: Date.now(), text, completed: false });
            this.newTodo = '';
        }
    },
    removeTodo(event, el, detail) {
        this.todos = this.todos.filter(t => t.id !== detail.item.id);
    },
    toggleTodo(event, el, detail) {
        detail.item.completed = event.target.checked;
    },
    setFilter(event, element) {
        this.filter = element.dataset.filter;
    },
    clearCompleted() {
        this.todos = this.todos.filter(t => !t.completed);
    }
});