<html>

<head>
  <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>

<body>

  <div x-data="todoList()">

    <h1>Todo List</h1>

    <input x-model="newTodoItem" placeholder="Add item...">
    <button x-on:click="addItem()">+ Add</button>

    <h3>Todo:</h3>

    <ul>
      <template x-for="(item,index) in getActiveItems" :key="item.id">
        <li>
          <input type="checkbox" x-model="item.isDone">
          <span x-text="item.title"></span>
        </li>
      </template>
    </ul>

    <h3>Completed:</h3>

    <ul>
      <template x-for="(item,index) in getCompletedItems" :key="item.id">
        <li>
          <input type="checkbox" x-model="item.isDone">
          <span x-text="item.title" style="text-decoration: line-through;"></span>
        </li>
      </template>
    </ul>

    <h3>Raw Model Data:</h3>

    <div style="border: 1px solid gray; padding: 8px;">
      <pre x-text="JSON.stringify(todoItems, null, 2)"></pre>
    </div>
  </div>
</body>

</html>
function todoList() {
  return {
    newTodoItem: "",

    todoItems: [
      {
        id: 1,
        title: "Tidy kitchen",
        isDone: true
      },
      {
        id: 2,
        title: "Buy catnip",
        isDone: false
      }
    ],

    getCompletedItems() {
      return this.todoItems.filter((a) => a.isDone).sort((a, b) => a.id - b.id);
    },

    getActiveItems() {
      return this.todoItems
        .filter((a) => !a.isDone)
        .sort((a, b) => a.id - b.id);
    },

    addItem() {
      if (!this.newTodoItem) {
        return;
      }

      this.todoItems.push({
        id: this.todoItems.length + 1,
        title: this.newTodoItem,
        isDone: false
      });

      this.newTodoItem = "";
    }
  };
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.