Menu

ToDo List with Signals

Port of the original Preact/signals ToDo example Playground

import { h, render } from "preact"
import { signal, computed } from "preact/signals";

const todos = signal([
  { text: "Write my first post", completed: true },
  { text: "Buy new groceries", completed: false },
  { text: "Walk the dog", completed: false },
]);

const completedCount = computed(() => {
  return todos.value.filter(todo => todo.completed).length;
});

const newItem = signal("");

function addTodo() {
  todos.value = [...todos.value, { text: newItem.value, completed: false }];
  newItem.value = ""; // Reset input value on add
}

function removeTodo(index) {
  todos.value.splice(index, 1)
  todos.value = [...todos.value];
}

const TodoList = () => {
  const onInput = event => {
      (newItem.value = event.target.value);
  }

  return <div class="bg-white">
      <div class="flex-row content-center" style={{alignItems:"Center"}}>
        <textfield class="m-1" text={newItem.value} onInput={onInput} label="Task" />
        <button style={{height:40}} onClick={addTodo} text="Add"/>
      </div>
      <ul>
        {todos.value.map((todo, index) => {
          return (
            <li>
                <div class="flex-row">
              <toggle
                value={todo.completed}
                onValueChanged={() => {
                  todo.completed = !todo.completed
                  todos.value = [...todos.value];
                }}
              />
              {todo.completed ? <s>{todo.text}</s> : todo.text}{' '}
              <button onClick={() => removeTodo(index)} text="❌"/>
              </div>
            </li>
          );
        })}
      </ul>
      <p>Completed count: {completedCount.value}</p>
      </div>
}

render(<TodoList />, document.body);