Back to Examples

Todo List

A todo list example demonstrating list state management, input binding, and iteration with the each loop.

Source Code

json
{
  "version": "1.0",
  "state": {
    "todos": {
      "type": "list",
      "initial": []
    },
    "newTodo": {
      "type": "string",
      "initial": ""
    }
  },
  "actions": [
    {
      "name": "setNewTodo",
      "steps": [
        {
          "do": "set",
          "target": "newTodo",
          "value": {
            "expr": "var",
            "name": "value"
          }
        }
      ]
    },
    {
      "name": "addTodo",
      "steps": [
        {
          "do": "update",
          "target": "todos",
          "operation": "push",
          "value": {
            "expr": "state",
            "name": "newTodo"
          }
        },
        {
          "do": "set",
          "target": "newTodo",
          "value": {
            "expr": "lit",
            "value": ""
          }
        }
      ]
    },
    {
      "name": "removeTodo",
      "steps": [
        {
          "do": "update",
          "target": "todos",
          "operation": "remove",
          "value": {
            "expr": "var",
            "name": "item"
          }
        }
      ]
    }
  ],
  "view": {
    "kind": "element",
    "tag": "div",
    "props": {
      "style": {
        "expr": "lit",
        "value": "font-family: system-ui, sans-serif; padding: 16px;"
      }
    },
    "children": [
      {
        "kind": "element",
        "tag": "h1",
        "props": {
          "style": {
            "expr": "lit",
            "value": "margin: 0 0 8px 0; font-size: 24px;"
          }
        },
        "children": [
          {
            "kind": "text",
            "value": {
              "expr": "lit",
              "value": "Todo List"
            }
          }
        ]
      },
      {
        "kind": "element",
        "tag": "p",
        "props": {
          "style": {
            "expr": "lit",
            "value": "color: #666; margin: 0 0 16px 0;"
          }
        },
        "children": [
          {
            "kind": "text",
            "value": {
              "expr": "lit",
              "value": "Add items and manage your todo list."
            }
          }
        ]
      },
      {
        "kind": "element",
        "tag": "div",
        "props": {
          "style": {
            "expr": "lit",
            "value": "display: flex; gap: 8px; margin-bottom: 16px;"
          }
        },
        "children": [
          {
            "kind": "element",
            "tag": "input",
            "props": {
              "type": {
                "expr": "lit",
                "value": "text"
              },
              "style": {
                "expr": "lit",
                "value": "flex: 1; padding: 8px 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; color: #333; background: white;"
              },
              "value": {
                "expr": "state",
                "name": "newTodo"
              },
              "onInput": {
                "event": "input",
                "action": "setNewTodo",
                "payload": {
                  "expr": "var",
                  "name": "value"
                }
              }
            }
          },
          {
            "kind": "element",
            "tag": "button",
            "props": {
              "style": {
                "expr": "cond",
                "if": {
                  "expr": "bin",
                  "op": "==",
                  "left": {
                    "expr": "state",
                    "name": "newTodo"
                  },
                  "right": {
                    "expr": "lit",
                    "value": ""
                  }
                },
                "then": {
                  "expr": "lit",
                  "value": "padding: 8px 16px; background: #ccc; color: #666; border: none; border-radius: 4px; cursor: not-allowed; font-size: 14px;"
                },
                "else": {
                  "expr": "lit",
                  "value": "padding: 8px 16px; background: #0070f3; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px;"
                }
              },
              "disabled": {
                "expr": "bin",
                "op": "==",
                "left": {
                  "expr": "state",
                  "name": "newTodo"
                },
                "right": {
                  "expr": "lit",
                  "value": ""
                }
              },
              "onClick": {
                "event": "click",
                "action": "addTodo"
              }
            },
            "children": [
              {
                "kind": "text",
                "value": {
                  "expr": "lit",
                  "value": "Add"
                }
              }
            ]
          }
        ]
      },
      {
        "kind": "element",
        "tag": "ul",
        "props": {
          "style": {
            "expr": "lit",
            "value": "list-style: none; padding: 0; margin: 0;"
          }
        },
        "children": [
          {
            "kind": "each",
            "items": {
              "expr": "state",
              "name": "todos"
            },
            "as": "item",
            "body": {
              "kind": "element",
              "tag": "li",
              "props": {
                "style": {
                  "expr": "lit",
                  "value": "display: flex; align-items: center; justify-content: space-between; padding: 12px; margin-bottom: 8px; background: #f5f5f5; border-radius: 4px;"
                }
              },
              "children": [
                {
                  "kind": "element",
                  "tag": "span",
                  "props": {
                    "style": {
                      "expr": "lit",
                      "value": "color: #333;"
                    }
                  },
                  "children": [
                    {
                      "kind": "text",
                      "value": {
                        "expr": "var",
                        "name": "item"
                      }
                    }
                  ]
                },
                {
                  "kind": "element",
                  "tag": "button",
                  "props": {
                    "style": {
                      "expr": "lit",
                      "value": "padding: 4px 12px; background: #dc2626; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;"
                    },
                    "onClick": {
                      "event": "click",
                      "action": "removeTodo",
                      "payload": {
                        "expr": "var",
                        "name": "item"
                      }
                    }
                  },
                  "children": [
                    {
                      "kind": "text",
                      "value": {
                        "expr": "lit",
                        "value": "Delete"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      }
    ]
  }
}

Features Used

  • List state
  • String state
  • Input binding with onInput
  • Each loop for iteration
  • List operations (push, remove)
  • Action payload passing

How to Run

npm install @constela/core @constela/runtime
npx constela run todo-list.json
Try in Playground