Skip to main content

FlexTextInput

Bjanczak\FilamentFlexFields\Filament\Forms\Components\FlexTextInput extends Filament TextInput. Filament owns persisted state, casts, validation, actions, relationships and binding modifiers. FLEX owns its presentation and optional browser tools. The browser tools use the native input binding, with no separate persisted-state engine.

Native compatibility

Use native email(), numeric(), integer(), password(), tel(), url(), type(), inputMode(), minValue(), maxValue(), step(), minLength(), maxLength(), length(), masks (including RawJs), stripCharacters(), datalist(), autocomplete, autofocus, capitalization and spellcheck as usual. Native validation, hydration/dehydration callbacks, disabled/read-only behavior, live()/lazy()/blur bindings, affixes, icons, colors, prefix/suffix actions, extraInputAttributes() and extraAlpineAttributes() remain available through inheritance. Native CopyAction, ShowPasswordAction and HidePasswordAction retain their visibility, disabled state, attributes and accessible labels. A mask uses native text-input rendering. Explicit type() is respected; password reveal only changes the DOM type when the native type is password and no mask is configured. Read-only fields may still offer copying. Clearing, suggestions, drafts, emoji and dictation cannot edit a disabled/read-only field. Native maxLength() has the browser’s UTF-16 maxlength semantics while native server string validation uses Laravel’s semantics. FLEX counterLimit() with enforceCounterLimit() provides a separate, explicitly selected unit on both client and server. Neither counter mode nor visual strength silently replaces native validation. Domain-specific validation still belongs to application rules.

Options

Options accept closures where their fluent signature allows them. Defaults and budgets are centralized in Support/TextInput/TextInputOptions.php; unsupported choices fail explicitly. Builder configuration uses the same contract with snake_case names (for example counter_mode, draft_lifetime). Callback-backed suggestions and verification belong to application PHP, not serialized config.

Counters

Word counting splits trimmed text on Unicode whitespace. Grapheme counting uses PHP Unicode clusters and browser Intl.Segmenter; an unsupported browser reports unavailable counting and rejects an enforced grapheme edit instead of changing the unit silently. Older ICU/Unicode versions can differ on newly introduced clusters. Server validation is authoritative. Large text is not segmented unless a counter, hard unit limit or reading-time feature needs it.

Editing and reading

Typing uses native DOM selection and IME composition. Tool edits dispatch one input event and preserve the relevant caret. Ctrl/Cmd+Z can undo the most recent FLEX tool edit while the input still matches its result; unrelated native edits invalidate that tool history. This is not a replacement for browser undo history. Normalization runs on blur and is opt-in; apply equivalent server normalization when the stored representation must satisfy an application rule.

Copying and toolbar

Native copyable(true, 'Copied!', 1200) configures the message and duration. Clipboard success is shown only after copying succeeds. The legacy fallback preserves source type, focus and selection. Loading stays in the input control, independent of toolbar visibility. A toolbar with no available actions leaves no separator or empty position.

Passwords

Configured requirements are checked by a server validation rule as well as the visual list. Strength is an advisory estimate, not entropy measurement or a breached-password service. Balanced mode penalizes common patterns and repeated characters. Requirements mode reports completion of the configured rules. Password fields reject drafts, suggestions, remote verification and text/paste normalization to prevent unintended persistence, disclosure or transformation.

Emoji and dictation

Enable with emojiPicker() and/or speechDictation(). Additional methods are emojiPickerLocale(), emojiPickerLabel(), speechDictationLanguage() and speechDictationLabel(). Browser support and permission still govern dictation. A browser network recognition error means communication with its speech service failed, even when the device remains online. The field displays that distinction. Only native SpeechRecognition / webkitSpeechRecognition is used; FLEX does not download or install speech models. Service access is provided by the browser. Click the microphone again to retry after an error. Stopping keeps the session busy until final results arrive. Final results are committed once through the native input event, updating Livewire state and the counter together. Finalized text survives a subsequent service error; interim text is never saved as a final transcript. Only one field in a document uses the recognition microphone at a time. Switching fields, revoking editability, hiding the document or disposing the owner retires its session and callbacks. Closing/removing/disabling its owner aborts a session and discards pending text. Emoji content loads only when opened. Input and textarea reuse one picker, Select’s positioning, portals, exclusivity and enter/exit transitions. Shared CSS has one owner; it is not copied into each consuming field. Default action icons use Hugeicons: Mic01 (the shape without a horizontal foot), LookTop and MultiplicationSign. Override with microphoneIcon(), emojiIcon(), clearIcon(), copyIcon(), copySuccessIcon(), showPasswordIcon() and hidePasswordIcon(). Password reveal uses ViewIcon / ViewOffIcon. All default FLEX icons are from the package’s Hugeicons set.

Suggestions, verification and drafts

City and User are example application models. Authorize tenant/user access inside callbacks. These independent examples use native skipRenderAfterStateUpdated() so a deferred text update bundled with a lookup does not replace the focused input. Keep normal rendering when your server-side state hooks must update other fields or the input configuration. Static suggestions accept at most 200 normalized records; value ≤512, label ≤120 and description ≤240 characters. Disabled records remain visible but cannot be selected; this is an option state, not a loading error. Free text remains permitted. Keyboard arrows, Enter and Escape, ARIA listbox/combobox semantics and retry feedback are built in. Suggestions use the same menu surface as Select, not a second overlay engine. Remote methods are exposed through Filament with renderless callbacks, bounded input and shared actor/field rate limiting. Single-flight work retains only the latest pending query; a small bounded cache avoids repeated suggestion requests. Late results cannot restore a disposed/disabled field. Callback verification returns success/error/warning and a message ≤512 characters; the field stays idle when verification is not eligible. This is advisory and does not replace submit-time server validation. Avoid putting sensitive values into remote verification callbacks. Drafts use pathname + explicit key, TTL and a maximum 8192 UTF-16 code units. Restoration only occurs into an empty field; it never overwrites filled server state. An empty edit removes the stored draft. Storage failures produce feedback. Use unique keys when several instances exist. Keep sensitive data out of browser drafts. No draft module is initialized without opting in.

Additional presentation API

variant(primary|secondary|flat|soft), size(sm|md|lg), rounding(native|none|sm|md|lg|xl|full) and focusOutline() preserve FLEX’s visual language. characterCounter(), clearable(), loading(), passwordStrength(), passwordStrengthLabels() and validating() enable their respective features. The password indicator has four neutral segments before editing. Weak and very weak values fill one red segment; fair values fill two amber segments; good and strong values fill three and four green segments. Fill transitions run in both directions, mirror in RTL, and respect reduced-motion preferences. Existing five-level passwordStrengthLabels() remain configurable. The indicator is an estimate; passwordRequirements() and native validation enforce your actual submission policy. When passwordRequirementsVisible() is enabled, each rule has its own row and circular check indicator. Green check indicators animate when rules are met, and their spoken met/not-met state is localized. The list follows RTL and stays in one column on small screens. Static badges use verificationStatus(), verificationStatusIcon() and verificationStatusColor() independently of async verification.

Demo and examples

The live demo groups examples by task: native input features, Unicode limits, editing, actions, passwords, emoji and dictation, suggestions and drafts, and appearance including RTL. Open Code Example for copyable PHP configurations. Only the active demo group loads its optional tools.

Loading and behavior

Plain inputs do not load icon or emoji catalogs. Enable only the tools your field needs: suggestions, verification, drafts and dictation load on demand, and the emoji picker loads its content when opened. Shared resources are reused across instances. Emoji and icon menus align to the whole input, rather than their toolbar button: right edge in LTR and left edge in RTL. Suggestions match the input’s width and align with its start edge. Menus follow resize and scroll, open above when space below is limited, and stay inside the viewport. Small screens use the shared mobile sheet. Removing a field, changing its capabilities or making it disabled/read-only releases its active tools and prevents late responses from changing its state. Normal Livewire value updates preserve the active controller.

Associated icon picker

Add an icon action inside the text input without a separate form row. The text remains a normal string, while the icon is a separate, server-validated value. The dropdown shares the existing Icon Picker: search, library filters, pagination, SVG caching, keyboard support and virtualized results.
The first argument is a relative sibling state path. A form with statePath('data') saves data.title and data.title_icon. In a repeater, each row keeps its own text and icon. Do not add a second Hidden or Icon Picker field for the same icon path: the embedded native field already owns hydration, validation and dehydration. Add a nullable string column for the icon when using ordinary Eloquent columns, or keep both keys in your JSON form data. The configuration callback accepts the ordinary Icon Picker API. Installed Blade icon sets are available through sets(); a library must be registered in your application before you select it. icons() restricts choices to explicit identities, and excludeIcons() removes identities. Both search results and save validation enforce the same policy.
Icon clearing is enabled by default: open the picker and choose Clear icon to save the associated icon as null. The text value is preserved, and a cleared icon stays empty after reload; the trigger displays the default picker symbol. Use clearable(false) in the callback to hide the clear action. Use required() if an empty icon must fail server validation. Available callback settings include sets(), icons(), excludeIcons(), searchResultsLayout('icons'|'grid'|'list'), gridColumns(), perPage(), limitPerSet(), preload(), closeOnSelect(), clearable(), label(), required() and native field validation hooks. The owner fixes the embedded state path, inline trigger and parent disabled/read-only boundary.
This composition API is configured in trusted PHP. It does not accept executable callbacks from stored JSON. Optional assets are declared for the rendered input; a plain text field does not acquire the Icon Picker. SVG pages are fetched when the dropdown opens unless preload() is explicitly enabled. Choosing an icon does not transmit or replace the text input’s value. For standalone compact triggers, IconPickerField::make('icon')->inlineTrigger() uses the same control without its usual select label/name presentation. Use the associated-input API above when it belongs to a text input.

Server-side value protection

FLEX rejects structured array/object values submitted to a scalar text input, including empty arrays. Optional empty and null values retain native Filament behavior. Required, email, URL, numeric, unique, length and application-specific rules still belong to the native form. Enforced Unicode limits and password requirements are checked on the server as well as shown in the browser. The animated strength meter and verifyUsing() feedback are advisory; use passwordRequirements(), native validation rules and your form’s save action to enforce the policy. Selecting an icon stores its name separately and validates it against the configured libraries and allowed list. Emoji and icon menus fit the viewport: at widths up to 768 px they use the shared mobile sheet; above that boundary they use a clamped desktop panel with automatic above/below placement. Their results scroll internally when height is limited. An empty search placeholder follows RTL, while entered Latin/Arabic text keeps native automatic text direction.
Last modified on October 16, 2026