# Як налаштувати поле «Список по API» (ActionJail)?

Тип **Список по API** підвантажує опції випадаючого списку з **ActionJail-дії** під час редагування запису. Це зручно, коли перелік значень динамічний (оператори, магазини, довідник з CRM) і не вміщується в статичний **Список**.

## Коли знадобиться

- Потрібен dropdown із даних, які змінюються (користувачі, статуси зовнішньої системи, довідник API).
- Статичний **Список** не підходить — занадто багато значень або вони оновлюються автоматично.
- **Системний** тип (Користувач, Тема…) не покриває ваш кейс — потрібна власна jail-дія.

## Що важливо знати

| Параметр у редакторі | Призначення |
|---------------------|-------------|
| **ActionJail-дія** | Технічна назва дії (`action_…`), яка повертає список |
| **Поле підпису в списку** (`label_key`) | Ключ у кожному елементі відповіді: **і підпис у списку, і значення, що збережеться в полі** після вибору |

**Де працює dropdown сьогодні**

- клієнтські поля в діалозі оператора;
- динамічні поля в операторських формах (Table view, OperatorLine);
- **не** у таблиці записів і **не** у боковій картці запису — там значення показується як текст, поки не буде окремо підключено вибір зі списку (заплановано).

**Коли обрати інший тип**

- фіксований перелік → **Список**;
- посилання на іншу таблицю Custom Data → **Звʼязок з таблицею**;
- користувач / тема / тег платформи → **Системні** типи.

## Перед початком

- [x] Є доступ до **ActionJail** (створення або редагування дії на інстансі).
- [x] Відкритий **Редактор моделі Custom Data** (або клієнтські поля в Settings).
- [x] Зрозуміло, які дані має повертати список і що саме зберігати в полі (ID, код, назва).

## Крок 1. Створити ActionJail-дію

1. Відкрийте **ActionJail** → **Створити дію** (або відредагуйте існуючу).
2. Задайте **технічну назву** — саме її оберете в полі моделі (наприклад `action_list_stores` або `aj_list_operators`).
3. У тілі дії:
   - прочитайте параметри запиту з констант: `query` (пошук), `limit`, `offset` — їх передає платформа при відкритті списку;
   - сформуйте масив елементів;
   - збережіть результат у `result` у форматі `{ rows, count }`;
   - поверніть `'success'`.

**Контракт відповіді**

```javascript
this.setCurrentStateConstant('result', {
  rows: [
    { id: 1, label: 'Київ — Центр' },
    { id: 2, label: 'Львів — Головний' },
  ],
  count: 2, // загальна кількість (для пагінації)
});
```

Кожен елемент `rows` — об'єкт. У ньому **обов'язково** має бути властивість з ім'ям, яке ви вкажете в **Полі підпису в списку** (типово `label`, `name` або `title`). Якщо в полі треба зберігати **ID**, вкажіть `label_key: id` — тоді в комірку потрапить значення `id` з обраного рядка.

**Мінімальний приклад дії**

```javascript
const appPath = process.cwd();
const OpModels = require(appPath + '/modules/extra/operator_panel/db/models');

async function action_list_active_operators() {
  const state = await this.getCurrentStateJSON();
  const query = String(state?.const?.query || '').trim();
  const limit = Number(state?.const?.limit) || 20;
  const offset = Number(state?.const?.offset) || 0;

  const where = { active: true };
  // за потреби — фільтр по query

  const rows = await OpModels.OpUsers.findAll({
    where,
    attributes: [ 'id', 'first_name', 'last_name' ],
    limit,
    offset,
    raw: true,
  });

  const formatted = rows.map((row) => ({
    id: row.id,
    label: [ row.first_name, row.last_name ].filter(Boolean).join(' '),
  }));

  this.setCurrentStateConstant('result', {
    rows: formatted,
    count: formatted.length,
  });

  return 'success';
}

module.exports = action_list_active_operators;
```

Платформа викликає дію через `GET /kw/tickets/custom_list/<назва_дії>` з query-параметрами `query`, `limit`, `offset`.

## Крок 2. Налаштувати поле в Custom Data

1. У редакторі моделі на вкладці **Поля** оберіть тип **Список по API**.
2. У блоці **Джерело списку**:
   - **ActionJail-дія** — ваша дія з кроку 1;
   - **Поле підпису в списку** — ключ для підпису та збереження (`label`, `id`, `name`…).
3. Збережіть модель.

У `columns_json` це виглядає так:

```json
"store_ref": {
  "type": "STRING",
  "label": "Магазин",
  "select_api_action": {
    "name": "action_list_stores",
    "label_key": "label"
  }
}
```

## Крок 3. Перевірити

1. Відкрийте форму оператора, де показується це поле (не таблицю даних, якщо dropdown там ще не підключено).
2. Відкрийте список — мають з’явитися рядки з дії.
3. Оберіть значення, збережіть — у БД має потрапити властивість з `label_key` обраного елемента.
4. Якщо список порожній — перевірте назву дії, логи ActionJail і що `result.rows` не порожній.

## Типові помилки

| Симптом | Що перевірити |
|---------|----------------|
| Порожній список | Назва дії в полі = назва в ActionJail; дія повертає `success` і `result.rows` |
| Підписи «undefined» | У кожному рядку є ключ із `label_key` |
| Зберігається не те значення | `label_key` визначає і підпис, і збережене значення — для ID використайте `id` |
| У таблиці даних лише текст | Очікувана поведінка; dropdown — в операторських формах |

## Пов'язані матеріали

- [Налаштувати тип поля](./configure-field-type.md)
- [Довідник семантичних типів полів](../reference/semantic-field-types-reference.md)
- [Налаштувати системні типи полів](./configure-system-field-types.md) — якщо підходить довідник платформи
