List view — Pagination, sorting, search and filters
The admin list view handles all its operations at the SQL level: pagination, column sorting, full-text search and value filters. Nothing is loaded into memory.
Displayed columns — list_display
By default, all entity columns are shown. Declaring list_display restricts the display to an ordered selection:
admin! {
users: users::Model => RegisterForm {
title: "Users",
list_display: [
["username", "Username"],
["email", "Email"],
["is_active", "Active"],
]
}
}
Each entry is a ["column_name", "Label"] pair. Columns declared in list_display also serve as the sorting whitelist: only these columns (and id) accept a sort_by parameter.
Available in the Tera context via visible_columns (list of names) and column_labels (corresponding labels).
Foreign key resolution
An optional third element in each list_display entry resolves a related table's label instead of displaying the raw ID:
admin! {
orders: order::Model => order::AdminForm {
title: "Orders",
list_display: [
["number", "N°"],
["user_id", "Customer", "eihwaz_users.username"], // ← FK
["status", "Status"],
],
}
}
The third element syntax is "table.column". The daemon automatically generates:
- In the list view: a
SELECT CAST(id AS TEXT), column FROM table WHERE id IN (...)post-processing query that replaces each ID with the resolved label. - In create and edit forms: a
<select>dropdown populated from the related table, with the existing value pre-selected in edit mode.
Resolution is compatible with i32, i64 and UUID — the identifier is cast to TEXT before comparison.
FK columns are automatically excluded from full-text search (searching a raw ID is meaningless). Non-FK columns remain indexed normally.
Common examples
["menu_id", "Menu", "menus.title"]
["theme_id", "Theme", "themes.label"]
["user_id", "Customer", "eihwaz_users.username"]
Configuring builtins — configure
list_display inside a resource body only applies to resources you declare. To configure display for builtin resources (users, droits, groupes) or to centralise all display config, use the top-level configure {} block:
admin! {
configure {
users: { list_display: [["id", "ID"], ["username", "Username"], ["email", "Email"]] },
droits: { list_display: [["id", "ID"], ["nom", "Name"]] },
}
blog: blog::Model => BlogForm { title: "Blog" }
}
The configure {} block supports list_display, list_exclude and list_filter. list_display and list_exclude are mutually exclusive.
Sidebar filters — list_filter
Declaring list_filter enables a sidebar showing the distinct values of each field:
admin! {
users: users::Model => RegisterForm {
title: "Users",
list_filter: [
["is_active", "Active"], // default: 10 values per page
["is_superuser", "Superuser"], // default: 10 values per page
["username", "Username", 5], // explicit limit: 5 values per page
]
}
}
- For each column, the daemon generates a SQL query that loads distinct values with
LIMIT/OFFSET. - Sidebar pagination (
‹ 1/N ›) is fully server-side via thefp_{column}URL parameter — no JavaScript required. - The per-page limit is configured per column via the optional 3rd element (default:
10). - Values are displayed as-is (
CAST(column AS TEXT)). Do not uselist_filteron foreign key (FK) oridcolumns — the raw value (35,128…) is not human-readable. Use the search bar instead. - Good candidates: booleans, enumerations, short codes (
lang,status,block_type). - Clicking a value applies a
WHERE column = valuefilter to the SQL query. - Multiple filters on different columns are combined with
AND.
Column sorting
Each column header is clickable. The resulting URL:
/admin/users/list?sort_by=email&sort_dir=asc&page=1
sort_by: column name (must be inlist_displayor beid)sort_dir:ascordesc- Changing the sort automatically resets to page 1
The current direction is shown by ▲ / ▼ in the header. Clicking the same column a second time reverses the direction.
Search
The search bar filters records across all visible text columns (ILIKE '%term%'). It preserves the active sort parameters.
/admin/users/list?search=alice&sort_by=email&sort_dir=asc
The entry counter reflects the filtered result.
Pagination
Pagination is computed at the SQL level (LIMIT / OFFSET). Page size is configured at the application level:
.with_admin(|a| {
a.site_title("Administration")
.auth(RuniqueAdminAuth::new())
.page_size(15) // ← entries per page (list views AND history)
})
page_size applies to both the resource list view and the history view (/admin/history). The default value is 10.
Active filters and search are preserved in pagination links.
URL parameters
| Parameter | Value | Description |
|---|---|---|
page | integer ≥ 1 | Current page (default: 1) |
sort_by | column name | Sort column |
sort_dir | asc | desc | Sort direction (default: asc) |
search | string | Search term |
filter_{column} | value | Active filter on a column |
fp_{column} | integer ≥ 0 | Current page of a sidebar filter group (0-indexed) |
All parameters can be combined. Priority order: filters → search → sort → pagination.