# hb-input-array-objects

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

## Summary

`hb-input-array-objects` is a repeating **object list** editor for structured records. It renders existing rows with **`hb-table`** (with row delete actions) and uses **`hb-form`** driven by **`schemaentry.params.schema`** to compose the next row. Submitting the nested form appends a new object to the value array and updates the table. When the page (or host) uses a **dark** Bulma theme (`prefers-color-scheme: dark`, `data-theme="dark"`, or `.theme-dark` on `html`/`body`/host), the slotted **Add** control is **`is-primary is-outlined`** for clearer contrast on dark surfaces.

The package registers **`hb-form`** and **`hb-table`** as dependencies (same bundle version as this component).

## Behavior

- **Schema:** `params.schema` is a **`hb-form`-compatible** array of field definitions (`type`, `id`, `label`, `params`, …). Nested **`type: "row"`** entries with **`params.columns`** are flattened when building table headers and cell keys: each column field’s **`id`** becomes a property on each stored object.
- **Value:** The live value is an array of plain objects. Each row should include a stable **`_objId`** string (used for table row identity and delete matching). If a row is missing **`_objId`**, the component falls back to a generated id when syncing the table.
- **Add row:** The add block is hidden when **`schemaentry.disabled`** is **`true`**. Table actions are empty in that case, so rows cannot be deleted.
- **Table:** Pagination is turned off (`disablepagination="yes"`). The only configured row action is **delete** (trash/remove style icon).
- **`setVal`:** Whenever the internal value or validity changes, the component dispatches **`setVal`** with **`{ value, valid, id }`**, where **`id`** is **`schemaentry.id`**. Duplicates are suppressed when the payload is unchanged.

### Validation

- If **`schemaentry.required`** is **`true`**, **`valid`** is **`true`** only when **`value`** is a non-empty array; otherwise **`valid`** is **`false`**.
- If **`required`** is not set or is **`false`**, **`valid`** is **`true`**.
- When **`show_validation`** is **`yes`**, **`schemaentry.validationTip`** is shown as Bulma **`help is-danger`** if the field is invalid.

## Styling (Bulma)

Bulma **1.x** is included in the shadow root. Theme the host (or ancestors) with **`--bulma-*`** variables so the table, buttons, and help text match the rest of the app. See [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/).

Host-level tokens documented for this component (see **`extra/docs.ts`** / **`styleSetup.vars`**):

| Variable | Role |
|----------|------|
| `--bulma-text` | Table labels, form labels, and help text |
| `--bulma-border` | Outer border around the table + add form block |
| `--bulma-danger` | Invalid validation message color |
| `--bulma-link` | Primary actions (for example the add-row control styled with Bulma’s info tone) |
| `--bulma-scheme-main` | Surface behind nested controls |
| `--bulma-radius` | Corner radius for buttons and table chrome |

## Custom element

`hb-input-array-objects`

## TypeScript

`types/webcomponent.type.d.ts` — `schemaentry` as `string | FormSchemaEntry | undefined`.

## Attributes (snake_case)

Web component attributes are **strings**. Complex data must be **JSON serialized** on the attribute (or set as a property from JavaScript).

| Attribute | Required | Description |
|-----------|----------|-------------|
| `schemaentry` | Yes | JSON string describing the field (see below). Parsed with the shared **`parseSchemaentryProp`** helper: accepts a JSON string or, from JS, an object. |
| `show_validation` | No | **`yes`** or **`no`**. Default in the implementation is **`no`**. When **`yes`**, invalid state shows **`validationTip`**. |
| `id` | No | Optional host element id. |
| `style` | No | Optional inline styles on the host. |

### `schemaentry` JSON shape

The serialized object matches **`FormSchemaEntry`** in **`types/webcomponent.type.d.ts`**, with **`params`** typed as **`InputArrayObjectsParams`**.

**Required**

- **`id`** — string; forwarded on **`setVal`** as **`detail.id`**.

**`params` (`InputArrayObjectsParams`)**

| Key | Description |
|-----|-------------|
| **`schema`** | Array of nested field definitions (same logical shape as rows passed to **`hb-form`**). This drives both the **add** form and the **table** columns. |
| **`columns`** | Optional mirror used like row-style layouts; rarely needed (see typings). |
| **`addPropertyLabel`** | String label for the add button when the **`add-object-label`** slot is not used. Default button text is **`Add item`**. |

**Optional top-level fields** (shared with other form entries; see **`FormSchemaEntryShared`** in **`hb-form`** typings)

Examples: **`value`** (initial array of rows), **`required`**, **`disabled`**, **`validationTip`**, **`placeholder`**, **`label`**, **`readonly`**, **`validationRegex`**, **`dependencies`**, etc.

**`value`** (when present) must be an array of objects. Each object should include **`_objId`** plus one property per flattened field **`id`** from **`params.schema`**.

## Events

| Event | `detail` |
|-------|----------|
| **`setVal`** | **`{ value: { _objId: string; [key: string]: unknown }[]; valid: boolean; id: string }`** — current rows, overall validity for this control, and the field **`id`**. |

Listen in HTML with **`addEventListener("setVal", …)`** or the equivalent in your framework.

## Slots

| Slot | Description |
|------|-------------|
| **`add-object-label`** | Optional **light DOM** content for the add-row button label. When present, it overrides **`params.addPropertyLabel`**. |

## CSS `::part` selectors

| Part | Description |
|------|-------------|
| **`properties-container`** | Wrapper around the repeating table and the add form (layout / border overrides from the light DOM). |
| **`invalid-feedback`** | The **`p.help.is-danger`** node used when **`show_validation="yes"`** and the value is invalid. |

## TypeScript

Authoring types for this package live in **`types/webcomponent.type.d.ts`**:

- **`Component`** — host props
- **`FormSchemaEntry`** / **`InputArrayObjectsParams`** — `schemaentry` shape
- **`Events`** — custom event payloads (e.g. **`setVal`**)

## Examples

### Minimal host markup

Use a single-line JSON attribute (or build the string in JavaScript).

```html
<hb-input-array-objects
  schemaentry='{"id":"people","params":{"schema":[{"type":"text","id":"name","label":"Name"}]}}'
  show_validation="no"
></hb-input-array-objects>
```

### Pre-filled rows

Each row needs **`_objId`** and keys matching field ids (here, **`firstName`** / **`lastName`** inside a **`row`**):

```html
<hb-input-array-objects
  schemaentry='{"id":"people","params":{"schema":[{"type":"row","id":"name-row","params":{"columns":[{"type":"text","id":"firstName","label":"First name"},{"type":"text","id":"lastName","label":"Last name"}]}}]},"value":[{"_objId":"1","firstName":"Ada","lastName":"Lovelace"}]}'
></hb-input-array-objects>
```

### Required list with visible validation

```html
<hb-input-array-objects
  schemaentry='{"id":"items","required":true,"validationTip":"Add at least one row.","params":{"schema":[{"type":"text","id":"title","label":"Title"}]}}'
  show_validation="yes"
></hb-input-array-objects>
```
