API Reference
Constructor
import ForgeSelect from "forge-select";
const select = new ForgeSelect(target, options);
target— a CSS selector string, or anHTMLSelectElement/HTMLElement.options— an options object (see below). All options are optional.
Options
| Option | Type | Default | Description |
|---|---|---|---|
placeholder |
string |
"" |
Text shown when nothing is selected. |
searchable |
boolean |
true |
Show a search input inside the dropdown. |
multiple |
boolean |
false |
Allow selecting more than one option. |
clearable |
boolean |
false |
Show a button to clear the current selection. |
allowCreate |
boolean |
false |
Let the user create a new option from free text (tags mode). |
sortable |
boolean |
false |
Multi-select only: let the user reorder selected tags by dragging (mouse/touch/pen), or with Alt+Left/Alt+Right when a tag has focus. |
theme |
string |
"default" |
Named theme applied via a data-theme attribute / CSS class. |
disabled |
boolean |
false |
Render the control as disabled. |
data |
Array<Option | OptionGroup> |
undefined |
Static options, used instead of <option> children. |
ajax |
AjaxConfig |
undefined |
Remote data source config (url, params, debounce, pagination, transform). |
templateResult |
(option) => string | Node |
undefined |
Custom renderer for dropdown list items. |
templateSelection |
(option) => string | Node |
undefined |
Custom renderer for the selected value display. |
virtualScroll |
boolean |
(auto) | true/unset = virtualize once the list exceeds ~100 rows; false = never virtualize. |
itemHeight |
number |
36 |
Row height in px used by the virtual scroller. Raise it (e.g. 52) for rich items with avatars/descriptions. |
language |
string | Record<string, string> |
"en" |
Locale code or a custom string table for i18n. |
plugins |
Array<ForgeSelectPlugin> |
[] |
Plugins to register on this instance. See the Plugin Development Guide. |
Option shape
interface Option {
value: string;
label: string;
disabled?: boolean;
avatar?: string; // image URL/data URI, shown as a round avatar
description?: string; // secondary line under the label
meta?: Record<string, unknown>; // arbitrary payload for custom templates
children?: Option[]; // nested options — makes this a tree node
}
interface OptionGroup {
label: string;
options: Option[];
}
Tree select (nested options)
Add children to any Option to turn it into an expandable/collapsible tree node — purely additive, so a list where no option has children renders and behaves exactly like a flat list:
new ForgeSelect("#categories", {
data: [
{
value: "fruits", label: "Fruits",
children: [
{ value: "apple", label: "Apple" },
{ value: "banana", label: "Banana" },
],
},
],
});
Nodes with children start collapsed and show a twisty (▶/▼) to expand/collapse; searching shows a node if it or any descendant matches, temporarily auto-expanding matching branches without disturbing manually-expanded state. In multiple: true mode, selecting a parent selects/deselects all of its descendants, and a parent whose descendants are only partially selected gets the forge-select__option--indeterminate class.
Sortable tags (drag & drop ordering)
With multiple: true, sortable: true, selected tags can be reordered by dragging (mouse/touch/pen, via Pointer Events) or with Alt+Left/Alt+Right when a tag has keyboard focus — both paths funnel through the same change event, so getValue() always reflects the current tag order. If mounted on a native <select multiple>, the underlying <option> elements are also reordered to match, so a plain <form> submission serializes values in the dragged order. Purely opt-in — multi-select behavior is unchanged when sortable is left at its default false.
Rich items
When an option has avatar and/or description and no custom template is set, Forge Select renders them with a built-in layout (avatar + label + description in the dropdown; small avatar + label in the selected value/tags). All built-in fields are inserted via textContent, so they are XSS-safe — no escaping needed on your side. description is also matched by the search filter.
Custom templates (templateResult/templateSelection) receive the full option including meta. A string return value is injected as raw HTML — sanitize any user-provided data yourself. Rendered row content is cached per option value and cloned on scroll, so templates run once per option regardless of scrolling; if your template returns a DOM Node, don't rely on event listeners attached inside it (clones don't carry listeners — use event delegation on the document instead).
AjaxConfig shape
interface AjaxConfig {
url: string | ((query: string) => string);
params?: (query: string, page: number) => Record<string, unknown>;
debounce?: number; // ms, default 250
pagination?: boolean; // opt in to loading further pages on scroll; default false
transform?: (response: unknown) => Option[] | { options: Option[]; hasMore: boolean };
}
By default ajax replaces the whole list on every search (transform returns a plain Option[], as above). Set pagination: true to additionally load more pages as the user scrolls near the bottom of the dropdown: params now also receives the current page (starting at 0), and transform should return { options, hasMore } so Forge Select knows whether to keep requesting further pages. A search query change always resets back to page 0 and replaces the list, regardless of pagination. See Examples for a full snippet.
Instance methods
| Method | Returns | Description |
|---|---|---|
.open() |
void |
Opens the dropdown. |
.close() |
void |
Closes the dropdown. |
.destroy() |
void |
Removes Forge Select and restores the original element. |
.getValue() |
string | string[] | null |
Returns the current value(s). |
.setValue(value) |
void |
Programmatically sets the current value(s). |
.enable() |
void |
Enables the control. |
.disable() |
void |
Disables the control. |
.on(event, handler) |
void |
Subscribes to an event (see below). |
.off(event, handler) |
void |
Unsubscribes a previously registered handler. |
Events
| Event | Payload | Fired when |
|---|---|---|
change |
value |
The selection changes. |
open |
— | The dropdown opens. |
close |
— | The dropdown closes. |
search |
query: string |
The search input value changes. |
clear |
— | The selection is cleared via the clear button. |
select.on("change", (value) => console.log(value));
select.on("search", (query) => console.log("searching:", query));
Framework wrappers
The constructor/options/methods/events above are the core forge-select API. Official wrapper components expose the same functionality with framework-native conventions:
| Package | Framework | Value binding |
|---|---|---|
forge-select-react |
React | value prop + onChange |
forge-select-vue |
Vue 3 | v-model |
Constructor-only options (data, templateResult, templateSelection, plugins, etc.) are read once when the wrapped instance mounts and are not reactive in either wrapper — see the Examples or each package's own README for details and the remount-with-key workaround.