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!