# For and Index

Source: https://signy.dev/documentation/1/templates/for-and-index/

Lists that update row by row.

## For

`For` renders one row per item. With `keyBy` or `key`, rows are reused and moved when the array changes. The item is a plain value and `index` is an accessor.

```js
const { Component, Signal, application, html, For } = Signy;

let nextId = 3;

class Todos extends Component {
  todos = new Signal([
    { id: 1, text: "Learn signals", done: new Signal(true) },
    { id: 2, text: "Write a component", done: new Signal(false) },
  ]);

  add(form) {
    const text = form.elements.text.value.trim();
    if (!text) return;
    this.todos.set((list) => [...list, { id: nextId++, text, done: new Signal(false) }]);
    form.reset();
  }

  remove(id) {
    this.todos.set((list) => list.filter((todo) => todo.id !== id));
  }

  render() {
    return html`
      <form class="group" onSubmit=${(e) => (e.preventDefault(), this.add(e.currentTarget))}>
        <input name="text" aria-label="New todo" placeholder="New todo" />
        <button>Add</button>
      </form>
      <ul>
        ${For({
          each: () => this.todos.value,
          keyBy: "id",
          fallback: html`<li>Nothing to do</li>`,
          children: (todo, index) => html`
            <li>
              <label>
                <input type="checkbox" checked=${todo.done.peek()}
                  onChange=${() => todo.done.set((done) => !done)} />
                ${() => index() + 1}. ${todo.text} ${() => (todo.done.value ? "✓" : "")}
              </label>
              <button class="small outlined" onClick=${() => this.remove(todo.id)}>Delete</button>
            </li>
          `,
        })}
      </ul>
    `;
  }
}

application(Todos).mount("#for-todos");
```

A field that changes on an item with the same key does not render again. Keep such fields in a signal on the item, like `done` above, or use a [store](https://signy.dev/documentation/1/reactivity/store/index.html.md).

## Index

`Index` is the other way round: the item is an accessor and the index a number. Rows stay in place and only their item changes. Use it for lists of primitives edited in place, and read `item()` inside a binding.

```js
const { Component, Signal, application, html, Index } = Signy;

class Scores extends Component {
  scores = new Signal([3, 7, 5]);

  bump(i) {
    this.scores.set((list) => list.map((score, j) => (j === i ? score + 1 : score)));
  }

  render() {
    return html`
      <ol>
        ${Index({
          each: () => this.scores.value,
          children: (score, i) => html`
            <li>
              ${() => score()} points
              <button class="small" onClick=${() => this.bump(i)}>+1</button>
            </li>
          `,
        })}
      </ol>
    `;
  }
}

application(Scores).mount("#index-scores");
```
