A fully interactive CRUD app using every built-in Signet.js directive.
Session started at ยท Signet.js Task Manager
These counters use js-scope โ no extra JS. The nested scope inherits step from the parent.
This app uses createApp() to define state, computed properties, and methods. The HTML template uses js-* directives to bind reactively to that state.
createApp({
tasks: [ /* initial tasks */ ],
newTask: '',
newPriority: 'medium',
filter: 'all',
// Methods auto-unwrap signals; use `this.x` not `this.x.value`
addTask() {
const text = this.newTask.trim();
if (!text) return;
this.tasks = [...this.tasks, {
text, done: false, priority: this.newPriority,
}];
this.newTask = '';
},
// Computed properties โ re-evaluate when deps change
get filteredTasks() {
if (this.filter === 'active')
return this.tasks.filter(t => !t.done);
if (this.filter === 'done')
return this.tasks.filter(t => t.done);
return this.tasks;
},
get total() { return this.tasks.length; },
get doneCount() { return this.tasks.filter(t => t.done).length; },
get progress() {
return this.total === 0
? 0
: Math.round(this.doneCount / this.total * 100);
},
}).mount('#app');
<!-- js-for creates a reactive list.
$index is the item's position. -->
<div js-for="task in filteredTasks">
<input
type="checkbox"
js-bind:checked="task.done"
js-on:click="toggleTask($index)"
/>
<span
js-text="task.text"
js-bind:class="task.done ? 'line-through' : ''"
></span>
<button js-on:click.stop="removeTask($index)">
โ
</button>
</div>
<!-- js-on:submit.prevent prevents default,
js-model provides two-way binding,
js-bind:disabled evaluates an expression -->
<form js-on:submit.prevent="addTask()">
<input js-model="newTask" type="text" />
<select js-model="newPriority">
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</select>
<button js-bind:disabled="newTask.length === 0">
Add
</button>
</form>
<!-- Parent scope provides `step` -->
<div js-scope="{ step: 1, parentCount: 0 }">
<button js-on:click="parentCount = parentCount + step">
+
</button>
<!-- Child inherits `step` from parent scope chain -->
<div js-scope="{ childCount: 0 }">
<!-- step is readable from the parent! -->
<span js-text="step"></span>
<button js-on:click="childCount = childCount + step">
+
</button>
</div>
</div>