Docs
Preferences

Array inputs

Repeating rows with their own schema, limits, summaries and per-row gates.

An array input collects any number of rows, each shaped by itemSchema:

{
  key: 'triggers',
  label: 'Triggers',
  type: 'array',
  minItems: 1,
  maxItems: 10,
  itemSummaryKeys: ['entity', 'state'],   // what a collapsed row shows
  itemSchema: {
    inputs: [
      { key: 'entity', label: 'Device', type: 'entity', required: true },
      { key: 'state', label: 'Changes to', type: 'enum', required: true,
        options: [ /* 'light.on', 'light.off', 'lock.locked', … */ ],
        filterOptionsByEntityDomain: 'entity' },    // narrow per row by the picked device's domain
    ],
  },
}

What your code receives

The global is a JSON array of plain row objects:

// triggers === [{ entity: 'binary_sensor.hall', state: 'binary_sensor.on' }, …]
function initialize() {
  for (const row of triggers ?? []) {
    const [, value] = row.state.split('.');
    subscribe(new EntityWrapper(row.entity), { to: value }, onTrigger);
  }
}

Entity fields inside rows are ids, not wrappers — wrap them with new EntityWrapper(id).

Row-level behaviour

Everything on Conditions and visibility works inside a row and refers to siblings in the same row: requiresEntityFeature, requiresSiblingOneOf, filterOptionsBySiblingPrefix, filterOptionsByEntityDomain, domainFilterFrom, unitFromEntity.

Tips

  • itemSummaryKeys keeps long lists readable; without it the app derives a summary from filled fields.
  • thermostatSchedule is a specialised array (a 7-day × 24-hour grid editor) that stores rows like { day, timeOfDay, hvacMode, heatSetpoint, coolSetpoint, fanMode } and hydrates like array.
  • The Simple Trigger example is a compact array-driven wizard: rows of actions with per-row option filtering and a dynamic preferences function. The Motion Light by Time of Day example uses rows with a multiple entity field and a brightness gated on the picked lights.

On this page