Skip to main content

CODE_WEB_TODO

Constant CODE_WEB_TODO 

Source
pub const CODE_WEB_TODO: &str = r##"# To-Do — add, finish, remove

`State:` holds an ordinary list of records. Each row is keyed by its id, so removing
one leaves the others' elements where they are. `left` is derived: it recomputes
whenever `todos` changes.

## A Todo has:
    an id, which is Int.
    a text, which is Text.
    a done, which is Bool.

## To openCount (todos: Seq of Todo) -> Int:
    Let mutable n be 0.
    Repeat for t in todos:
        If t's done is equal to false:
            Set n to n + 1.
    Return n.

## Page /

State:
    Let todos be a new Seq of Todo.
    Let draft be "".
    Let nextId be 1.
    Let left always be openCount(todos).

Actions:
    To add:
        If draft is equal to "":
            Return.
        Push (a new Todo with id nextId and text draft and done false) to todos.
        Set nextId to nextId + 1.
        Set draft to "".

    To toggle (id: Int):
        Let mutable next be a new Seq of Todo.
        Repeat for t in todos:
            If t's id is equal to id:
                Push (a new Todo with id t's id and text t's text and done (not t's done)) to next.
            Otherwise:
                Push t to next.
        Set todos to next.

    To remove (id: Int):
        Let mutable kept be a new Seq of Todo.
        Repeat for t in todos:
            If t's id is not equal to id:
                Push t to kept.
        Set todos to kept.

View:
    <h1>To-Do</h1>
    <form id="add" on-submit.prevent={add}>
      <input id="draft" type="text" aria-label="New task" bind={draft} placeholder="What needs doing?">
      <button type="submit">Add</button>
    </form>
    <ul>
      {for each t in todos, keyed by t's id:}
        <li class="todo" class:done={t's done}>
          <button id="toggle-{t's id}" on-click={toggle(t's id)}>{t's text}</button>
          <button id="remove-{t's id}" on-click={remove(t's id)}>remove</button>
        </li>
      {else:}
        <li class="empty">Nothing to do.</li>
      {end}
    </ul>
    <p id="left">{left} left</p>

Style:
    .done button:first-child { text-decoration: line-through; opacity: .6; }

## Test: todos are added, finished and removed

Type "milk" into "#draft".
Submit "#add".
Type "bread" into "#draft".
Submit "#add".
Expect that the count of ".todo" is equal to 2.
Click "#toggle-1".
Expect that the text of "#left" is equal to "1 left".
Click "#remove-1".
Expect that the count of ".todo" is equal to 1.
Expect that the text of "#toggle-2" is equal to "bread".
"##;
Expand description

Web page: a to-do list you add to, tick off and remove from — records in State:, a form with .prevent, a keyed {for each} with an empty arm, and a derived count.