# `hb-input-select`

**Category:** inputs · **Tags:** inputs

## Description

`hb-input-select` renders a native `<select>` inside the shadow DOM, driven entirely by the **`schemaentry`** prop (serialized JSON on the host). Options come from **`params.options`**: each entry is an **`InputSelectOption`** with a stable **`id`**, a string **`value`**, and an optional **`label`** (the visible text defaults to **`value`** when **`label`** is omitted).

The control respects **`required`**, **`disabled`**, and **`readonly`** from the schema. Because HTML selects do not support `readonly`, **`readonly`** is applied the same way as **`disabled`** (non-interactive select).

With **`show_validation="yes"`** and **`required`**, Bulma modifiers **`select.is-success`** / **`select.is-danger`** reflect validity, and **`validationTip`** is shown as **`p.help.is-danger`** when the value is invalid. **`is_small="yes"`** adds Bulma **`select.is-small`** for a compact control (for example next to **`hb-paginate`**).

On every meaningful change of **`value`**, **`valid`**, or field **`id`**, the element dispatches a bubbling **`setVal`** custom event. When **`schemaentry`** is updated later (for example from a parent form) and the component realigns the internal value from JSON, it avoids emitting a duplicate **`setVal`** if the payload matches what was already reported—so consumers are not treated as if the user changed the field again.

If **`schemaentry`** is missing or cannot be parsed into a field, nothing is rendered.

## Custom element

| Name | Tag |
| --- | --- |
| `hb-input-select` | `<hb-input-select …></hb-input-select>` |

## Attributes (snake_case; string values in HTML)

Web component attributes are always strings. Pass booleans as **`yes`** or **`no`**. Pass the schema as a **JSON string** (for example via **`setAttribute("schemaentry", JSON.stringify(...))`** in JavaScript).

| Attribute | Required | Description |
| --- | --- | --- |
| `schemaentry` | Yes | JSON string describing the field (see below). |
| `show_validation` | No | **`yes`** or **`no`**. Component default is **`no`** when the prop is unset. Toggles success/danger styling and the validation tip. |
| `is_small` | No | **`yes`** or **`no`**. Component default is **`no`** when unset. When **`yes`**, applies Bulma **`select.is-small`**. |

Optional host passthroughs supported by the typings (when your setup forwards them):

| Attribute | Required | Description |
| --- | --- | --- |
| `id` | No | Host element id. |
| `style` | No | Inline styles on the host. |

## `schemaentry` JSON shape

The serialized object extends the shared form schema entry (see **`FormSchemaEntryShared`** in the form typings) with select-specific **`params`**. At minimum you should supply **`id`** and, for a visible control, **`params.options`**.

Typical keys:

| Key | Description |
| --- | --- |
| `type` | Use **`"select"`** for clarity when generating JSON; the host already implies a select. |
| `id` | Stable field id; echoed in **`setVal`** **`detail.id`**. |
| `label` | Optional; useful for surrounding forms even though this component only renders the control and help text. |
| `placeholder` | Optional; reserved for higher-level form UIs. |
| `value` | Optional initial or controlled value (string, number, or boolean in JSON; coerced to string internally). |
| `required` | When **`true`**, an empty selection is invalid. |
| `readonly` / `disabled` | When set, the `<select>` is disabled. |
| `validationTip` | Message shown when invalid and **`show_validation`** is on. |
| `params` | **`InputSelectParams`** (see next table). |

### `params` (`InputSelectParams`)

| Key | Type | Description |
| --- | --- | --- |
| `options` | **`InputSelectOption[]`** | List of choices. Each item needs **`id`** and **`value`**; **`label`** is optional. Use **`value: ""`** with a blank label for a placeholder row on optional fields. |

## Events

| Event | `detail` |
| --- | --- |
| **`setVal`** | **`{ value: string; valid: boolean; id: string }`** — current option value (often **`""`** when a placeholder option is chosen), whether the field satisfies **`required`**, and the field **`id`**. |

Listen with **`addEventListener("setVal", ...)`** or your framework’s equivalent.

## Styling (Bulma)

The shadow tree bundles Bulma **1.x** Sass modules **`form/shared`**, **`form/select`**, and **`form/tools`**, with theme setup on **`:host`** (`--bulma-hb-def-*`). Override public **`--bulma-*`** on **`body`** or **`:root`** so they inherit onto the component host. See the [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/) documentation.

### CSS custom properties (common overrides)

| Variable | Role |
| --- | --- |
| `--bulma-text` | Selected option text and help message color. |
| `--bulma-border` | Select wrapper border before success/danger states. |
| `--bulma-danger` | Invalid **`select.is-danger`** and **`help.is-danger`**. |
| `--bulma-success` | Valid **`select.is-success`** when validation feedback is shown. |
| `--bulma-link` | Dropdown arrow / focus accents on the Bulma **`select`** control. |
| `--bulma-scheme-main` | Native `<select>` surface inside the shadow root. |

### CSS parts

| Part | Role |
| --- | --- |
| **`invalid-feedback`** | The **`p.help.is-danger`** node when **`show_validation`** is **`yes`** and the required field is invalid. |

### HTML slots

None.

### Markup outline

- Outer **`div.field`** > **`div.control`** > **`div.select`** (Bulma wrapper) > native **`<select>`**.
- Optional **`p.help.is-danger`** with **`part="invalid-feedback"`** when validation is shown and the value fails **`required`**.

## Typings

**`types/webcomponent.type.d.ts`** exports **`InputSelectOption`**, **`InputSelectParams`**, **`FormSchemaEntry`**, **`Component`**, and **`Events`** for authors and wrappers.

## Examples

### JavaScript (recommended for `schemaentry`)

```js
const el = document.querySelector("hb-input-select");

el.setAttribute(
  "schemaentry",
  JSON.stringify({
    type: "select",
    id: "country",
    label: "Country",
    required: true,
    validationTip: "Please choose a country.",
    value: "it",
    params: {
      options: [
        { id: "it", label: "Italy", value: "it" },
        { id: "fr", label: "France", value: "fr" },
        { id: "de", label: "Germany", value: "de" },
      ],
    },
  }),
);

el.setAttribute("show_validation", "yes");
el.setAttribute("is_small", "no");

el.addEventListener("setVal", (e) => {
  console.log(e.detail); // { value, valid, id }
});
```

### Static HTML (JSON in a single-quoted attribute)

Use single quotes around the attribute value so the JSON can contain double quotes unescaped. If the JSON itself must contain apostrophes, escape those in JSON strings as **`\'`** or prefer the JavaScript example.

```html
<hb-input-select
  schemaentry='{"type":"select","id":"country","required":true,"value":"it","params":{"options":[{"id":"it","label":"Italy","value":"it"},{"id":"fr","label":"France","value":"fr"}]}}'
  show_validation="yes"
  is_small="no"
></hb-input-select>
```
