Tag input

A token field: type a value, press Enter to add it, click the × to remove one. The tag list is a keyed data-each, and @keydown.enter.prevent keeps the form from submitting.

Markup

<template data-each="tags" data-key="id">
  <span>
    <span data-text="item.label"></span>
    <button @click="remove" data-bind="data-id:item.id" aria-label="Remove tag">&times;</button>
  </span>
</template>

<input data-model="draft" @keydown.enter.prevent="add" placeholder="Add a tag and press Enter" />

Component

Micra.define("taginput", {
  state: {
    draft: "",
    tags: [
      { id: 1, label: "design" },
      { id: 2, label: "frontend" },
    ],
  },
  add() {
    const t = this.state.draft.trim();
    if (!t) return;
    this._n = (this._n || 100) + 1;
    this.state.tags = [...this.state.tags, { id: this._n, label: t }];
    this.state.draft = "";
  },
  remove(e) {
    const id = Number(e.currentTarget.dataset.id);
    this.state.tags = this.state.tags.filter((t) => t.id !== id);
  },
});

Adding and removing both replace tags with a new array — a top-level write — so the keyed list diff updates only the chips that actually changed.