Skip to content

API reference

The full Tags surface: props, the two-way tokens model, change events, the imperative handle, and the scoped slot. For the per-framework consumption code see the usage page; for the live widget see the demo.

Props

The full prop surface. modelValue is the sole model: true prop — the committed tokens array — so the Angular output emits a ControlValueAccessor (a tags input is a form control). Boolean props default false (negative opt-out).

NameTypeDefaultTwo-way (model)RequiredDescription
modelValueArray[]The committed tokens — model: true, so a commit/remove/paste writes a fresh array back through r-model:modelValue (uncontrolled fallback []). Because it is the sole model prop, the Angular output is a ControlValueAccessor ([formControl] / [(ngModel)] bind directly).
delimitersArray[…]The keys that commit the current draft as a token (matched against the key event's key). Default [',', 'Enter']. Non-'Enter' entries also act as the split characters when pasting bulk text. Use e.g. [' ', 'Enter'] for a space-delimited input.
allowDuplicatesBooleanfalseAllow the same token value to be added more than once. Defaults to false — a candidate equal (case-sensitive) to an existing token is silently rejected on commit. Set true to permit duplicates.
maxNumbernullMaximum number of tokens. Once the list reaches max, the input is disabled and further adds (type, paste, programmatic) are rejected. null (the default) means unlimited.
disabledBooleanfalseDisable the whole control — the text input is disabled, every remove button is disabled, and no token can be added or removed. Also sets the Angular CVA disabled state.
readonlyBooleanfalseRender the tokens read-only — they remain visible but cannot be added or removed, and the text input is hidden. Unlike disabled it carries no disabled styling, so it reads as a display of committed values.
validateFunctionnullOptional per-token validator / normalizer. Called with (candidate, tokens) for each commit; return a (possibly normalized) string to accept it, or a falsy value (false / null / "") to reject the candidate. Runs before the dedup + max checks. Example: v => /^\S+@\S+$/.test(v) ? v.toLowerCase() : false for emails.
placeholderString''Placeholder text for the inline text input (e.g. "Add a tag…").
ariaLabelStringnullAccessible name for the whole control (role="group"). The inline text input is labelled with the same name so assistive tech announces what is being entered. A visually-hidden live region announces the current token count on change.

Events

Every mutation of the committed list emits change (the new full array), so you can observe the list without two-way binding. Individual mutations also emit add / remove. A rejected candidate (duplicate, failed validate, or over max) emits nothing.

EventDescription
addFired when a token is committed (an accepted Enter / comma / paste add). Payload { value, tokens } — the newly added token string and the fresh full array.
removeFired when a token is removed (a chip remove-button click or Backspace in an empty input). Payload { value, index, tokens } — the removed token, its former index, and the fresh full array.
changeFired on every committed-list mutation (add, remove, paste-bulk-add, or a programmatic clear). Payload { value } — the new full tokens array.

Imperative handle

Declared once in the source via $expose; obtained through each framework's native ref mechanism.

MethodDescription
clearRemove every token (emits change with { value: [] }) and move DOM focus to the text input. Collision-safe — not a host-element member.
focusMove DOM focus to the inline text input. Deliberately named focus, which overrides the inherited HTMLElement.focus on the Lit custom element — the public focus() handle is the intended semantics (an accepted, warn-only ROZ137 on the Lit leaf). This mirrors the otp/slider precedent and is consistent with NumberField.

Slots

SlotParamsDescription
tagtag, index, removeScoped — fully replaces the rendering of each chip. tag is the token string, index its position, and remove() a zero-arg function that removes this token. The default fallback renders the built-in chip (label + remove button). On React the slot is a render-prop children callback (the documented cross-framework slot divergence).

The slot name tag deliberately does not equal any prop key (ROZ127 — a slot/prop name collision is a hard error because Svelte 5 collapses snippets and props into one $props() bag).

Pre-v1.0 — internal monorepo.