makeGenList in webapp/js/gen-list.js renders every entity list of the web app from EntityMeta.list_view. This page lists its options, the parts of the screen, the cell formatters, and the selection and deactivation behaviour. webapp/js/table-align.js keeps table headers aligned with their columns. The metadata classes are on metadata model.
Scope and source¶
- Defined in:
webapp/js/gen-list.js(makeGenList,formatCell,buildRowParts,preloadFkColumns),webapp/js/table-align.js(initTableAlign,alignTableHeaders) - Count: 10 column formatters handled by
formatCell(counted from thefmt ===branches inwebapp/js/gen-list.js:86-129and theactive_flaghandling inbuildRowParts)
Options and presentation¶
makeGenList(moduleName, entityKey, opts) returns a render function (webapp/js/gen-list.js:338-372).
| Option | Effect | Source |
|---|---|---|
endpointKey |
The endpoint key used for the list call; default list |
webapp/js/gen-list.js:431-437 |
table |
Shows every list column as a full table instead of the summary row | webapp/js/gen-list.js:476-541 |
listEndpoint |
Selects which sidebar section description is shown above the list | webapp/js/gen-list.js:377-386 |
Without table, each row shows an avatar, a title, a secondary line, and badges built by buildRowParts (webapp/js/gen-list.js:230-298). With table, all list_view.columns are shown, numbers aligned right, booleans centred, and an avatar column when the entity declares photo (webapp/js/gen-list.js:481-541). Module apps set table from the catalogue flag tableList (webapp/js/home.js:2423-2431).
Screen parts¶
| Part | Shown when | Source |
|---|---|---|
| Search field | list_view.search_enabled is true; input is debounced by 200 ms |
webapp/js/gen-list.js:582-597, webapp/js/gen-list.js:1010 |
| Density chip | Always; cycles the three row densities | webapp/js/gen-list.js:582-590 |
| Section description | The sidebar section that shows this list has a description |
webapp/js/gen-list.js:377-386 |
Active / Passive segment (deactivate.segment_active, deactivate.segment_inactive) |
The entity has a delete endpoint and the user holds <entity_type>.read |
webapp/js/gen-list.js:405, webapp/js/gen-list.js:600-611 |
| Filters | list_view.filters exist; enum filters with three choices or fewer render as a segmented control, others as a select |
webapp/js/gen-list.js:654-700 |
Add New row (common.add) |
The entity has a create endpoint and the user holds <entity_type>.create |
webapp/js/gen-list.js:702-711 |
Actions chip (toolbar.actions) in the navigation bar |
The entity has actions that are not single_record |
webapp/js/gen-list.js:544-580 |
| Pager | list_view.paginated is not false |
webapp/js/gen-list.js:723 |
| Empty state | No rows; a filtered empty list offers Clear filters (glist.clear_filters) |
webapp/js/gen-list.js:725-737, webapp/js/gen-list.js:305-323 |
Page size is PAGE_LIMIT = 50 (webapp/js/ui.js:7). When the server reports total_capped, the pager marks the total as capped (webapp/js/gen-list.js:446-448).
Cell formatters¶
formatCell(colMeta, value, ctx) formats a value by ColumnMeta.formatter (webapp/js/gen-list.js:86-129).
| Formatter | Output | Source |
|---|---|---|
i18n_message |
Translates the row's <key>_key with <key>_params in the reader's language; the stored value is the fallback |
webapp/js/gen-list.js:91-97 |
boolean |
Yes or No (common.yes, common.no) |
webapp/js/gen-list.js:99 |
date |
YYYY-MM-DD in the user's time zone |
webapp/js/gen-list.js:100, webapp/js/prefs.js:150-154 |
datetime |
YYYY-MM-DD HH:MM:SS in the user's time zone |
webapp/js/gen-list.js:101, webapp/js/prefs.js:172-179 |
enum |
The choice label from the column, a filter, or the form field | webapp/js/gen-list.js:102-111 |
foreign_key |
The display value from the preloaded reference list | webapp/js/gen-list.js:112-116 |
entity_type |
The localised label of an entity type | webapp/js/gen-list.js:118 |
entity_record |
The owner record's title for polymorphic references | webapp/js/gen-list.js:121-125 |
active_flag |
A badge for active or passive rows in the summary row | webapp/js/gen-list.js:255-262 |
decimal |
The value as sent; used for right alignment | webapp/js/gen-list.js:69-84 |
Decimal values arrive as strings and are not converted to numbers for display. isNumericValue only decides alignment (webapp/js/gen-list.js:56-67). This follows the money rule on money and Decimal.
Foreign-key columns are resolved by preloadFkColumns, which loads each column's display_endpoint list and asks the records labels endpoint for ids that are not in it, such as deactivated records (webapp/js/gen-list.js:149-215). See boot, session, and API calls for the reference list cache.
Selection and bulk operations¶
| Behaviour | Rule | Source |
|---|---|---|
| Enter selection | Press and hold a row for 450 ms without moving more than 8 px; the row starts selected | webapp/js/gen-list.js:1101-1111, webapp/js/ui.js:71-119 |
| Selection is offered | The user can delete, or the entity has single_record actions |
webapp/js/gen-list.js:1103 |
| Selection bar | Select All, the count, Actions for exactly one row, Share, and Delete | webapp/js/gen-list.js:620-651 |
| Delete | Asks for a deactivation reason, then calls bulkDelete |
webapp/js/gen-list.js:846-868 |
| Reactivate | In the passive view, reactivates each selected row | webapp/js/gen-list.js:868-893 |
| Leave selection | Cancel (common.cancel) in the navigation bar |
webapp/js/gen-list.js:552-569 |
The project's written engineering rules state that selection is entered by press and hold, that row actions open from a card at the bottom, and that inline edit and delete are forbidden. The list follows this: a tap opens the record and editing starts from the card.
Opening a row¶
openRow(row) follows this order (webapp/js/gen-list.js:816-844):
- If the entity declares
identityand the row carries the link field, the canonical record's card opens (a facet opens the party card). - Else, if the entity has
detail_view,makeGenDetailopens. - Else, if the entity has form groups, a read-only record card with an edit button opens.
A passive row opens a read-only card with the deactivation reason and a reactivate button (webapp/js/gen-list.js:895-933). An entity with create_with_file creates its record through the add-document screen (webapp/js/gen-list.js:787-800).
Refresh¶
The list subscribes to the data-changed signal and reloads when a change in the same module happened after its last load (webapp/js/gen-list.js:368-372). See data refresh and change signals.
Header alignment¶
initTableAlign() runs once at boot and watches the document. For every table with one header row and no spanning cells, it sets each header cell's text alignment to the computed alignment of the first data cell in its column (webapp/js/table-align.js:1-78, webapp/js/main.js:230). The comment states that this covers hand-written tables in app bundles as well. web-client/_e2e_table_alignment.mjs measures the result in a browser.
Constraints and validation¶
- Create, update, delete, and view-passive entries depend on both the declared endpoint and the user's permission code (
webapp/js/gen-list.js:396-406). - Actions with scope
parentare never offered in a list (webapp/js/gen-list.js:407). - Browser tests:
web-client/_e2e_action_sheet.mjs(press and hold),web-client/_e2e_density.mjs,web-client/_e2e_tenant_fields_list.mjs.
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| press and hold | bindLongPress |
Holding a pointer on a row for 450 ms to enter selection mode. | basılı tut | webapp/js/ui.js:71 |
| passive view | listInactive |
The list of deactivated records of an entity. | Pasifler | webapp/js/gen-api.js:151 |
| cell formatter | formatCell |
The function that turns a column value into display text by its formatter. | hücre biçimleyici | webapp/js/gen-list.js:86 |
Related pages¶
- Web app platform
- Metadata rendering
- Generic detail
- Actions and action sheet
- Search, pagination, and bulk operations
Verified against commit 92f8051 on 2026-11-13.