Trying to add a checkbox that also line-throughs my list item when completed:true

Not sure how much code you need, I've console.log("test"); which worked, and console.log({todos}); also worked, however even when clicking the checkbox, it would show as completed:false every time... I'm not really sure where the bug is. I've also noticed this .completed css selector isn't working, but it's clearly shown below in the todoCard div, so I'm also not entirely sure why vsc is saying it's an unused css selector.
.completed {
text-decoration: line-through;
.completed {
text-decoration: line-through;
<script>
let todos = [];
let newTodo = '';

function addTodo() {
if (newTodo.trim() === '') {
return;
}
todos = [...todos, { text: newTodo, completed: false }];
newTodo = '';
}

function removeTodo(index) {
todos = todos.filter((_, i) => i !== index);
}

function toggleCompleted(index) {
todos[index].completed = !todos[index].completed;
todos = [...todos];
}
</script>
<script>
let todos = [];
let newTodo = '';

function addTodo() {
if (newTodo.trim() === '') {
return;
}
todos = [...todos, { text: newTodo, completed: false }];
newTodo = '';
}

function removeTodo(index) {
todos = todos.filter((_, i) => i !== index);
}

function toggleCompleted(index) {
todos[index].completed = !todos[index].completed;
todos = [...todos];
}
</script>
<div class="todoCard">
<input type="text" bind:value={newTodo} placeholder="Add a new todo" />
<button on:click={addTodo}>Add</button>
<ul>
{#each todos as todo, index (todo.text)}
<li class:todo.completed={todo.completed}>
<input
type="checkbox"
bind:checked={todo.completed}
on:change={() => toggleCompleted(index)}
/>
{todo.text}
<button on:click={() => removeTodo(index)}>Remove</button>
</li>
{/each}
</ul>
</div>
<div class="todoCard">
<input type="text" bind:value={newTodo} placeholder="Add a new todo" />
<button on:click={addTodo}>Add</button>
<ul>
{#each todos as todo, index (todo.text)}
<li class:todo.completed={todo.completed}>
<input
type="checkbox"
bind:checked={todo.completed}
on:change={() => toggleCompleted(index)}
/>
{todo.text}
<button on:click={() => removeTodo(index)}>Remove</button>
</li>
{/each}
</ul>
</div>
5 Replies
VinceAggrippino
VinceAggrippino8mo ago
That's probably overkill...
<input type="checkbox" name="milk" id="milk">
<label for="milk">Milk</label>
<input type="checkbox" name="milk" id="milk">
<label for="milk">Milk</label>
input:checked + label {
text-decoration: line-through;
}
input:checked + label {
text-decoration: line-through;
}
CDL
CDL8mo ago
I believe the way I'm trying to do it is tracking state, but the above probably wouldn't no?
CDL
CDL8mo ago
Not sure if this works, but I hope it lets you look and edit
VinceAggrippino
VinceAggrippino8mo ago
I might not understand completely. I'm not familiar with Svelte at all. Changing the text decoration for checked items and tracking the state of the checked items seem like completely unrelated things to me. I don't know if it'll help your or not, but I did up a functioning To-Do without a framework. The line-through is handled in CSS like I suggested earlier. The state of the completed items is stored in a global variable like it looks like you're doing. I hope this helps: https://codepen.io/VAggrippino/pen/poGRpvZ
theoriginalandrew
Step 1, remove Svelte GoodMeme were pretty close to the solution, what was missing was passing in the checked value into the toggleCompleted function. Technically the bind doesn't really do anything in your case, but if you set completed: true in the addTodo function, that truthy value would get passed in and set the checkbox checked by default instead. https://codesandbox.io/p/sandbox/wonderful-hofstadter-cxqh2d?file=%2Fsrc%2Flib%2Fcomponents%2FTodo.svelte%3A21%2C3