Tags input component for PhiaUI.
Provides tags_input/1 — a multi-tag input field that renders existing tags
as removable badge chips and lets users add new tags by typing and pressing
Enter (or a configurable separator character).
Tags are managed client-side by the PhiaTagsInput JS hook, which handles:
- Adding a tag on Enter or separator key
- Removing a tag via the × button or Backspace on an empty input
- Deduplication (ignores duplicate values)
- Syncing the hidden
<input>with the current tag CSV for form submission
The component integrates with Phoenix.HTML.FormField so changeset validation
errors are displayed automatically.
When to use
Use tags_input/1 for any field that accepts a variable number of string
values — article labels, skill tags, email recipients, keyword lists, etc.
Registration
Register the hook in app.js:
import PhiaTagsInput from "./hooks/tags_input"
let liveSocket = new LiveSocket("/live", Socket, {
hooks: { PhiaTagsInput }
})Basic form example
<.form for={@form} phx-submit="save_article">
<.tags_input
field={@form[:tags]}
label="Tags"
placeholder="Add a tag..."
/>
<.button type="submit">Save</.button>
</.form>Custom separator
By default, pressing , (comma) or Enter adds a tag. You can change the
separator to ; or any other character:
<.tags_input
field={@form[:emails]}
label="Recipients"
placeholder="Type an email and press Enter..."
separator=";"
/>Value formats
The component accepts the field value in either format:
| Format | Example |
|---|---|
| CSV string | "elixir,phoenix,liveview" |
| List of strings | ["elixir", "phoenix"] |
Empty strings and whitespace-only values are filtered out automatically.
Changeset integration
Tags are serialised as a comma-separated string in the hidden input. In your changeset, cast and split the CSV field:
defmodule MyApp.Article do
use Ecto.Schema
import Ecto.Changeset
schema "articles" do
field :tags, {:array, :string}
end
def changeset(article, attrs) do
# tags arrive as CSV string "elixir,phoenix" from the form
tags =
case attrs["tags"] do
nil -> []
csv -> String.split(csv, ",", trim: true)
end
article
|> cast(Map.put(attrs, "tags", tags), [:tags])
|> validate_required([:tags])
end
endAlternatively, store tags as a single delimited string and split on read.
Summary
Functions
Renders a multi-tag input integrated with Phoenix.HTML.FormField.
Functions
Renders a multi-tag input integrated with Phoenix.HTML.FormField.
Initial tags are parsed from field.value (list or CSV string) and rendered
server-side. The PhiaTagsInput hook takes over on mount and manages all
client-side add/remove/dedup/sync behaviour.
The hidden <input> is kept in sync by the hook and carries the current
tag CSV on form submit, which the changeset receives as a string.
Attributes
field(Phoenix.HTML.FormField) (required) - APhoenix.HTML.FormFieldfrom@form[:field_name]. Providesid,name,value, anderrorsfor full form integration.label(:string) - Label text rendered above the input. Passnilto omit the label. Defaults tonil.placeholder(:string) - Placeholder text shown in the text input when it is empty. Defaults to"Add tag...".separator(:string) - Character that triggers adding the current input value as a new tag, in addition to the Enter key. Defaults to",". ThePhiaTagsInputhook reads this fromdata-separator.Defaults to
",".class(:string) - Additional CSS classes for the outer wrapper div. Defaults tonil.