Todo list#
<div todo-space>
<template todo-item-tpl>
<div todo-item>
<i val val-fx="Pattr" val-key="status" val-attr="todo-item-status" hidden></i>
<input type="checkbox" todo-item-checkbox onchange="Todo.Check(this)" />
<span todo-item-text val val-fx="Text" val-key="text"></span>
<button onclick="Todo.Remove(this)">remove</button>
</div>
</template>
<div todo-items val-tpl="[todo-item-tpl]"></div>
<div todo-add val val-fx="Obj">
<input val val-fx="Input" val-key="text" type="text" />
<button onclick="Todo.Add(this)">add</button>
</div>
<pre todo-output></pre>
</div>
const Todo = (() => {
const Add = (ctx) => {
const space = ctx.up('[todo-space]');
const add = space.one('[todo-add]');
space.one('[todo-items]').vappend([{ ...add.val(), status: 'todo'}]);
add.val({ text: '' });
Output(space);
};
const Check = (ctx) => {
ctx.up('[todo-item]').set(d => ({ ...d, status: d.status === 'done' ? 'todo' : 'done' }));
Output(ctx.up('[todo-space]'));
};
const Remove = (ctx) => {
const space = ctx.up('[todo-space]');
ctx.up('[todo-item]').remove();
Output(space);
};
const Output = (space) => {
space.one('[todo-output]').textContent = JSON.stringify(space.one('[todo-items]').varr(), null, 4);
}
return {
Add,
Check,
Remove,
}
})();
The todo-item-status attribute is a contract. The HTML, the JavaScript, and the CSS all use it. The CSS styles the done item straight from the attribute. There is no active class toggled in JavaScript, so changing the style never means changing the code.
[todo-item][todo-item-status="done"] [todo-item-text] {
text-decoration: line-through;
}