#[non_exhaustive]pub struct Grid { /* private fields */ }Expand description
A data grid’s definition: its columns and defaults. Cheap to build, so a function returning it is the usual place for one.
Implementations§
Source§impl Grid
impl Grid
Sourcepub async fn export<M: Model + Serialize>(
&self,
query: Query<M>,
request: &GridRequest,
) -> Result<Option<Response>>
pub async fn export<M: Model + Serialize>( &self, query: Query<M>, request: &GridRequest, ) -> Result<Option<Response>>
Answers the export menu’s links (?export=csv|xlsx|print): None
when the request isn’t an export, so the handler goes on to draw the
page.
use renox::grid::{Column, Grid, GridRequest};
fn orders() -> Grid {
Grid::new("orders").column(Column::text("number", "Order")).exports()
}
async fn index(request: GridRequest) -> Result<Response> {
if let Some(file) = orders().export(Order::query(), &request).await? {
return Ok(file);
}
let page = orders().page(Order::query(), &request).await?;
Ok(view("orders/index.html", context! { orders => page }).into_response())
}Custom columns are left out, and so are the columns the user hid on
wide screens. Up to MAX_EXPORT_ROWS rows.
Sourcepub async fn export_as<M: Model + Serialize>(
&self,
query: Query<M>,
format: ExportFormat,
request: &GridRequest,
) -> Result<Response>
pub async fn export_as<M: Model + Serialize>( &self, query: Query<M>, format: ExportFormat, request: &GridRequest, ) -> Result<Response>
Every row query matches as a file, outside the grid’s page: an
“Export” action on a record’s page or in a menu (the grid’s own
export menu uses Grid::export). The grid’s columns that show by
default on wide screens, in their order; the request’s filters,
sort and the user’s column choices don’t apply (sort the query
yourself). Up to MAX_EXPORT_ROWS rows.
use renox::grid::{Column, ExportFormat, Grid, GridRequest};
fn ledger() -> Grid {
Grid::new("ledger").column(Column::number("quantity", "Quantity"))
}
// GET /products/{id}/ledger.csv
async fn export_ledger(Path(id): Path<i64>, request: GridRequest) -> Result<Response> {
let movements = Movement::where_eq("product_id", id).order_by("id");
ledger().export_as(movements, ExportFormat::Csv, &request).await
}Source§impl Grid
impl Grid
Sourcepub fn new(id: &str) -> Self
pub fn new(id: &str) -> Self
A grid named id (letters, digits, _ and -), which keys each
user’s preferences and the element’s id.
Sourcepub fn poll(self, seconds: u32) -> Self
pub fn poll(self, seconds: u32) -> Self
Reloads the grid’s page every seconds (at least 5) while the tab is
visible and nobody is editing, selecting or filtering in it.
Sourcepub fn remember(self) -> Self
pub fn remember(self) -> Self
Keeps the user’s filters, search, sort, group and page size in the session: coming back to the page shows the grid as they left it.
Sourcepub fn advanced_filter(self) -> Self
pub fn advanced_filter(self) -> Self
An advanced filter in the toolbar: rules on any filterable column
(“Total is greater than 1,000,000”, “Name doesn’t contain coffee”,
“Ordered before 2026-03-01”, “Email is empty”), all or any of them
holding. They travel in the query string (match=any&r.0.c=total& r.0.o=gt&r.0.v=1000000), next to the headings’ filters.
Sourcepub fn cards_on_mobile(self) -> Self
pub fn cards_on_mobile(self) -> Self
On phones (under 768 px) each row is a card: the columns picked for small screens stacked as label and value, with sorting and filters in the toolbar. Wider screens keep the table.
Sourcepub fn groups(self, keys: &[&str]) -> Self
pub fn groups(self, keys: &[&str]) -> Self
Columns the user may group rows by (a “Group” choice in the toolbar): each group starts with a heading (its value and how many rows it has, folding its rows away on a click) and ends with its own summaries. Rows are sorted by the group first.
Sourcepub fn group_by(self, key: &str) -> Self
pub fn group_by(self, key: &str) -> Self
Groups rows by key until the user picks otherwise (it joins
Grid::groups).
Sourcepub fn bulk_action(self, action: Action) -> Self
pub fn bulk_action(self, action: Action) -> Self
An action on the selected rows: a checkbox starts each row, and
selecting some shows the actions over the grid. The action is sent
to its URL (with the grid’s query string, for “all matching”) as
Selection; the grid reloads after a 2xx.
Sourcepub fn row_action(self, action: Action) -> Self
pub fn row_action(self, action: Action) -> Self
An action in each row’s menu (⋯); {id} in its URL is the row’s id.
Sourcepub fn selected<M: Model>(
&self,
query: Query<M>,
request: &GridRequest,
selection: &Selection,
) -> Result<Query<M>>
pub fn selected<M: Model>( &self, query: Query<M>, request: &GridRequest, selection: &Selection, ) -> Result<Query<M>>
query narrowed to what a bulk action was sent for: the selected
ids, or every row the grid’s filters match when the user chose
“all matching”.
use renox::grid::{Action, Column, Grid, GridRequest, Selection};
fn orders() -> Grid {
Grid::new("orders")
.column(Column::text("status", "Status"))
.bulk_action(Action::new("Mark paid", "/orders/paid"))
}
async fn mark_paid(State(db): State<Db>, request: GridRequest, Form(selection): Form<Selection>) -> Result<String> {
let changed = orders()
.selected(Order::query(), &request, &selection)?
.update(&db, &[("status", &"paid")])
.await?;
Ok(format!("{changed} orders paid"))
}Sourcepub fn prefix(self, prefix: &str) -> Self
pub fn prefix(self, prefix: &str) -> Self
Prefixes the grid’s query string names (orders.page=2,
orders.q.number=…), for pages with more than one grid. Without
it the names are plain (page=2). Either way a grid keeps the query
string values that aren’t its own.
Sourcepub fn row_url(self, url: &str) -> Self
pub fn row_url(self, url: &str) -> Self
A click on a row (outside its buttons and links) opens this URL,
{id} replaced by the row’s id; Ctrl/Cmd-click opens it in a new tab.
With row details (Grid::audit, Grid::details) a click opens
those instead and the row tools get a link.
Sourcepub fn empty_state(self, heading: &str, description: Option<&str>) -> Self
pub fn empty_state(self, heading: &str, description: Option<&str>) -> Self
What an empty grid (before any filter) says; the page’s call block
can add buttons for column.key == "_empty".
Sourcepub fn exports(self) -> Self
pub fn exports(self) -> Self
An export menu in the toolbar: CSV, Excel (with the xlsx feature)
and a page to print or save as PDF, each of every row the filters
match (not just the page), in the user’s columns. The handler answers
them with Grid::export.
Sourcepub fn audit(self) -> Self
pub fn audit(self) -> Self
A click on a row (or its chevron) opens details under it: who
created and last changed the row, and when, from its created_by,
created_at, updated_by and updated_at values (those it has).
Sourcepub fn details(self) -> Self
pub fn details(self) -> Self
A click on a row opens details under it, drawn by the page’s
template: caller(row, column) with column.key == "_details".
With Grid::audit, the audit fields come first.
Sourcepub fn edit_url(self, url: &str) -> Self
pub fn edit_url(self, url: &str) -> Self
Where edits are sent: PATCH to this URL with {id} replaced by the
row’s id, the changed fields as a form (customer=…, tags=a&tags=b,
paid=true). Answer with a 2xx (a Toast shows), or with
Valid<T>’s 422 and the errors show next to the fields; the grid
then reloads its page.
Sourcepub fn reorder(self, column: &str, url: &str) -> Self
pub fn reorder(self, column: &str, url: &str) -> Self
Rows can be dragged into order (or moved with the arrow keys on
their handle) while the grid is sorted by column ascending; the
new order of the page is POSTed to url as ids and offset
(see RowOrder).
Sourcepub fn per_page(self, per_page: u32) -> Self
pub fn per_page(self, per_page: u32) -> Self
Rows per page until the user picks another number (default 25).
Sourcepub fn sort_by(self, sort: &str) -> Self
pub fn sort_by(self, sort: &str) -> Self
The order before the user sorts: a column key, - first for
descending ("-created_at"), or several separated by commas
("region,city,-total", what merged columns want). Ties are broken
by id.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Grid
impl RefUnwindSafe for Grid
impl Send for Grid
impl Sync for Grid
impl Unpin for Grid
impl UnsafeUnpin for Grid
impl UnwindSafe for Grid
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more