/ PLAYGROUND
To-do app A Lucid-powered to-do app. This uses two components - a master component, and a child component for each 'to do' item.
<!-- COMPONENT MASTER -->
<div>
<h1>Lucid to-do app!</h1>
<p>
<input id=newTodo placeholder='Add a new to-do...' data-lmodel=newTodo>
<button onclick=addTodo>Add</button>
</p>
<ul>
<Todo todo={{$value}} />
</ul>
<p id=markDone><button onclick=markDone disabled>Mark done</button></p>
</div>
<script>
//to-do items container
this.data.todos = [];
//set iteration on list
this.repeaters = {
Todo: this.data.todos
};
//mark-all button available only if some to-dos added
this.conditionals = {
'#mark-all-done': () => this.data.todos.length
};
//on 'add', add new to-do item
this.events.addTodo = () => {
if (!this.data.newTodo) return;
this.data.todos.push({
task: this.data.newTodo,
done: false
});
this.data.newTodo = '';
this.reprocessReps();
this.reprocessConds();
};
//router for messages from other components...
this.on('message', (comp, data) => {
switch (data.msg) {
//...from child 'Todo' component - reassess 'mark done' button disabled status
case 'checkboxToggled':
let btn = this.DOM.querySelector('#markDone button');
data.state ? btn.removeAttribute('disabled') : btn.setAttribute('disabled', 1);
break;
}
});
//mark all items done
this.events.markDone = () => {
this.message('todo', {msg: 'markDone'});
this.DOM.querySelector('#markDone button').disabled = 1;
};
</script>
<style>
* { font-family: sans-serif; }
#newTodo { width: 200px; padding: 8px; }
button { background: salmon; padding: 9px 15px; color: white; border: none; border-radius:4px; font-weight: bold; cursor: pointer; position: relative; }
button[disabled] { opacity: .5; }
</style>
<!-- COMPONENT TODO -->
<li class=done-{{todo.done}}>
<input type=checkbox>
<span>✔</span>
{{todo.task}}
[
<a class='mark done'>mark done</a>
<a class='mark not-done'>mark not done</a>
]
</li>
<script>
//conditionally show either 'mark done' or 'mark not done' link - likewise done tick
this.conditionals = {
'.mark.done': () => !this.data.todo.done,
'.mark.not-done': () => this.data.todo.done,
span: () => this.data.todo.done
};
//mark done/not done
this.DOM.onclick = evt => {
if (!evt.target.matches('.mark')) return;
this.data.todo.done = !this.data.todo.done;
this.rc();
};
//checkbox for master's 'mark done' button - on toggle, tell parent to reassess whether button disabled or not
this.DOM.onchange = evt => {
this.message('parent::*', {msg: 'checkboxToggled', state: evt.target.checked});
};
//router for messages from other components...
this.on('message', (comp, data) => {
switch (data.msg) {
//...'mark all' button clicked - mark item as done
case 'markDone':
let cb = this.DOM.querySelector('[type=checkbox]');
if (!cb.checked) return;
cb.checked = false;
this.data.todo.done = true;
this.rc();
break;
}
});
</script>
<style>
span { color: #0c0; }
</style>
//JS object of route data (optional)
{}
//JS object of filter methods (optional)
{}
//JS object of start data for master component
{}
Hi!