How to configure a «List by API» (ActionJail) field?
The List by API type loads dropdown options from an ActionJail action while the operator edits a record. Use it when values are dynamic (operators, stores, an external catalog) and do not fit a static List.
When you need this
- You need a dropdown backed by changing data (users, external statuses, API catalog).
- A static List is not enough — too many values or they update automatically.
- System types (User, Subject, …) do not fit — you need a custom jail action.
What to know
| Editor setting | Purpose |
|---|---|
| ActionJail action | Technical action name (action_…) that returns the list |
List label field (label_key) | Property on each item: both the dropdown label and the value saved in the field after selection |
Where the dropdown works today
- client fields in the operator dialog;
- dynamic fields in operator forms (Table view, OperatorLine);
- not in the record table or record side card yet — value is shown as plain text until list selection is wired there (planned).
When to pick another type
- fixed enum → List;
- link to another Custom Data table → Table link;
- platform user / subject / tag → System types.
Before you start
Access to ActionJail (create or edit an action on the instance). Custom Data model editor open (or client fields in Settings). You know what the list should return and what must be stored (ID, code, label).
Step 1. Create an ActionJail action
- Open ActionJail → Create action (or edit an existing one).
- Set the technical name — the same name you will pick in the field config (e.g.
action_list_storesoraj_list_operators). - In the action body:
- read request params from constants:
query(search),limit,offset— passed by the platform when the list opens; - build an array of items;
- store the result as
{ rows, count }inresult; - return
'success'.
- read request params from constants:
Response contract
this.setCurrentStateConstant('result', {
rows: [
{ id: 1, label: 'Kyiv — Center' },
{ id: 2, label: 'Lviv — Main' },
],
count: 2,
});
Each rows item is an object. It must include a property whose name matches List label field (commonly label, name, or title). To store an ID, set label_key to id — the cell will receive the selected row's id.
Minimal action example
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 };
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;
The platform calls the action via GET /kw/tickets/custom_list/<action_name> with query, limit, offset.
Step 2. Configure the field in Custom Data
- In the model editor Fields tab, choose List by API.
- In List source:
- ActionJail action — your action from step 1;
- List label field — key for label and stored value (
label,id,name, …).
- Save the model.
In columns_json:
"store_ref": {
"type": "STRING",
"label": "Store",
"select_api_action": {
"name": "action_list_stores",
"label_key": "label"
}
}
Step 3. Verify
- Open an operator form where the field is shown (not the data table if the dropdown is not wired there yet).
- Open the list — rows from the action should appear.
- Select a value and save — the database should contain the property named in
label_key. - If the list is empty — check action name, ActionJail logs, and that
result.rowsis non-empty.
Common issues
| Symptom | What to check |
|---|---|
| Empty list | Field action name matches ActionJail; action returns success and result.rows |
Labels show undefined | Each row includes the label_key property |
| Wrong stored value | label_key controls both label and stored value — use id for IDs |
| Plain text in data table | Expected; dropdown is in operator forms |