pub struct DataGrid<E: Model> { /* private fields */ }Expand description
Data grid. Its data source is an action that takes a DataQuery and returns Page<E>.
Example:
DataGrid::of(search_products).column(Product::code).width(120).filter()Implementations§
Source§impl<E: Model> DataGrid<E>
impl<E: Model> DataGrid<E>
Sourcepub fn group_by<T: FieldType>(self, field: Field<E, T>) -> Self
pub fn group_by<T: FieldType>(self, field: Field<E, T>) -> Self
Groups rows by field on the server; call again to group inside each group. The grid
shows a header row per group with its value, row count and the column totals over the
group, and loads a group’s rows (or subgroups) when the user opens it, a page at a time.
The top level pages over groups. The grid’s action answers DataQuery::group with
Page::groups; DataQuery::apply does it for in memory data. Virtual grids do not group.
Masked fields never group a grid, because a group shows its value: such a call is ignored
and logged.
Sourcepub fn tree<K: FieldType>(self, parent: Field<E, Option<K>>) -> Self
pub fn tree<K: FieldType>(self, parent: Field<E, Option<K>>) -> Self
Shows rows as a tree by their parent key: rows whose parent is empty at the top, and the
children of a row loaded when the user opens it, a page at a time, to any depth (at most
[MAX_TREE_DEPTH]). The parent field must be optional; empty means a top row. Filters and
sorting apply at every level, totals cover every matching row. Tree grids do not group
and show no row details; virtual grids show no tree.
Sourcepub fn detail<S: ScreenDef>(
self,
detail: impl Fn(&E) -> (S, S::Params) + Send + Sync + 'static,
) -> Self
pub fn detail<S: ScreenDef>( self, detail: impl Fn(&E) -> (S, S::Params) + Send + Sync + 'static, ) -> Self
Lets every row expand into a screen built from the row, loaded only when the user opens
it: .detail(|o: &Order| (order_lines, OrderParams { id: o.id })). Params of the wrong type
do not compile. The detail can hold anything a screen holds, such as another grid with its
own detail, to any depth. The expander shows only for users who may open the screen, and
the server checks the screen’s permission again when it loads, as for any screen. The
params travel through the browser like a window’s, so the detail screen checks that the
user may see the record they name.
Virtual grids (Paging::Virtual) keep every row at one fixed height and show no expander;
use pages or infinite paging for grids with details.
Sourcepub fn sort_by<T: FieldType>(self, field: Field<E, T>, desc: bool) -> Self
pub fn sort_by<T: FieldType>(self, field: Field<E, T>, desc: bool) -> Self
The order rows come in before the user sorts: .sort_by(Order::id, true) for newest
first. The header shows it, and clicking that column only switches between ascending and
descending; other columns go back to this order on their third click. Call it again to add
further keys. The action still receives it in DataQuery::sort.
Sourcepub fn scope<T: FieldType>(self, field: Field<E, T>, value: T) -> Self
pub fn scope<T: FieldType>(self, field: Field<E, T>, value: T) -> Self
Keeps only the rows whose field equals value, on every request, whatever the client
sends: .scope(OrderLine::order_id, params.id) for the lines of one order. The filter goes
first in DataQuery::filters, so a data layer that reads the filters keeps it. Text
compares ignoring case.
Sourcepub fn exportable(self) -> Self
pub fn exportable(self) -> Self
Lets users export every row that matches their filters as CSV, in their column layout and
language. The server pages through the grid’s action and streams the file, up to
DEFAULT_EXPORT_LIMIT rows. Exporting needs the grid’s read access. The toolbar’s
Export::Csv button uses this export when the grid has it.
Sourcepub fn export_permission(self, permission: &'static str) -> Self
pub fn export_permission(self, permission: &'static str) -> Self
Like exportable, but exporting also needs permission.
Sourcepub fn export_limit(self, rows: usize) -> Self
pub fn export_limit(self, rows: usize) -> Self
Most rows one export may hold; bigger results are cut there. At most 1,000,000.
Sourcepub fn edit_with<A>(self, _save: A) -> Self
pub fn edit_with<A>(self, _save: A) -> Self
Lets users edit cells of the columns marked editable() in place, saved with save, an
action that takes Valid<E> like a form’s. The server loads the row again by key, applies
only the editable columns and the row version (#[version]) the client sends, validates
and runs the action; a changed row comes back as a conflict. F2 or a double click on an
editable cell starts editing, Enter saves, Escape cancels, Ctrl+Z undoes the last save.
Context menu of each row, built on the server from the row. Right click, Shift+F10 or the
context menu key opens it. See crate::ContextMenu.
Sourcepub fn auto<A>(source: A) -> Self
pub fn auto<A>(source: A) -> Self
DataGrid with a column for every field of the model except the row version, in declaration order, and filter boxes on text and choice columns. The quickest list for a simple model.
pub fn mode(self, mode: DataMode) -> Self
Sourcepub fn paging(self, paging: Paging) -> Self
pub fn paging(self, paging: Paging) -> Self
Paging style. Numbered pages of 50 rows unless set.
Sourcepub fn column<T: FieldType + 'static>(
self,
field: Field<E, T>,
) -> DataGridColumn<E, T>
pub fn column<T: FieldType + 'static>( self, field: Field<E, T>, ) -> DataGridColumn<E, T>
Adds a column. The following settings (width, filter…) apply to it.
Sourcepub fn row_style(
self,
style: impl Fn(&E) -> Option<RowStyle> + Send + Sync + 'static,
) -> Self
pub fn row_style( self, style: impl Fn(&E) -> Option<RowStyle> + Send + Sync + 'static, ) -> Self
Picks a highlight per row.
Sourcepub fn on_open(
self,
open: impl Fn(&E) -> Effect + Send + Sync + 'static,
) -> Self
pub fn on_open( self, open: impl Fn(&E) -> Effect + Send + Sync + 'static, ) -> Self
What happens when a row is opened (double click or Enter).
Sourcepub fn row_action<A>(
self,
label: impl Into<Text>,
_action: A,
input: impl Fn(&E) -> A::Input + Send + Sync + 'static,
) -> Self
pub fn row_action<A>( self, label: impl Into<Text>, _action: A, input: impl Fn(&E) -> A::Input + Send + Sync + 'static, ) -> Self
Adds a button to every row that runs action with input built from the row:
.row_action(t!("stock.archive"), archive_product, |p| p.id). The button only shows for
users with the action’s permission. When pressed, the server loads the row again by its key
through the grid’s action, builds the input from it, checks the permission again and runs
the action; the client never sends the input.
Sourcepub fn selectable(self) -> Self
pub fn selectable(self) -> Self
Adds a checkbox to every row and a selection bar above the grid. Shift selects a range, the header box selects the page, and the bar offers every row that matches the filters.
Sourcepub fn bulk_action<A, K>(
self,
label: impl Into<Text>,
_action: A,
_key: Field<E, K>,
) -> Selfwhere
A: BulkAction<K> + Action<Input = Vec<K>>,
A::Output: Outcome,
K: DeserializeOwned + Send + 'static,
pub fn bulk_action<A, K>(
self,
label: impl Into<Text>,
_action: A,
_key: Field<E, K>,
) -> Selfwhere
A: BulkAction<K> + Action<Input = Vec<K>>,
A::Output: Outcome,
K: DeserializeOwned + Send + 'static,
Adds a button to the selection bar that runs action with the keys of the selected rows:
.bulk_action(t!("stock.archive"), archive_products, Product::id) where archive_products
takes Vec<ProductId>. Makes the grid selectable. The button shows only for users with the
action’s permission, which the server checks again. When the user picks every matching
row, the server collects the keys itself (at most MAX_BULK). Keys picked one by one come
from the client, so the action must check that the user may change each record, as an API
action would.
Sourcepub fn open_effect(&self, row: &E) -> Option<Effect>
pub fn open_effect(&self, row: &E) -> Option<Effect>
Effect produced when the row is opened.
Trait Implementations§
Source§impl<E: Model> Component for DataGrid<E>
impl<E: Model> Component for DataGrid<E>
fn render(&self, out: &mut String, r: &Render<'_>)
fn grid(&self) -> Option<&dyn GridSource>
fn form(&self) -> Option<&dyn FormSource>
Source§fn reveal(&self, _field: &str) -> Option<Revealed>
fn reveal(&self, _field: &str) -> Option<Revealed>
Source§fn import(&self) -> Option<&dyn ImportSource>
fn import(&self) -> Option<&dyn ImportSource>
crate::Import).Source§fn children(&self) -> &[Node]
fn children(&self) -> &[Node]
i of the node at path p has the path p.i.Source§fn eager_children(&self) -> &[Node]
fn eager_children(&self) -> &[Node]
Source§impl<E: Model, T> From<DataGridColumn<E, T>> for DataGrid<E>
impl<E: Model, T> From<DataGridColumn<E, T>> for DataGrid<E>
Source§fn from(c: DataGridColumn<E, T>) -> Self
fn from(c: DataGridColumn<E, T>) -> Self
Source§impl<E: Model> GridSource for DataGrid<E>
impl<E: Model> GridSource for DataGrid<E>
Source§fn reveal(
&self,
ctx: Ctx,
key: String,
field: String,
) -> BoxFuture<Result<Option<Revealed>>>
fn reveal( &self, ctx: Ctx, key: String, field: String, ) -> BoxFuture<Result<Option<Revealed>>>
Reveals a masked column of one row. The row is loaded like a row action’s, through the grid’s scope, so only rows the grid shows can be revealed.
fn action(&self) -> ActionMeta
Source§fn first_query(&self, view: Option<&DataGridView>) -> DataQuery
fn first_query(&self, view: Option<&DataGridView>) -> DataQuery
Source§fn clean_view(&self, view: DataGridView) -> DataGridView
fn clean_view(&self, view: DataGridView) -> DataGridView
Source§fn head_html(&self, r: &Render<'_>, view: Option<&DataGridView>) -> String
fn head_html(&self, r: &Render<'_>, view: Option<&DataGridView>) -> String
Source§fn find_row(&self, ctx: Ctx, key: String) -> BoxFuture<Result<LoadedPage>>
fn find_row(&self, ctx: Ctx, key: String) -> BoxFuture<Result<LoadedPage>>
GridSource::row_call picks the matching one.Source§fn bulk_call(&self, index: usize, keys: Vec<Value>) -> Option<RowCall>
fn bulk_call(&self, index: usize, keys: Vec<Value>) -> Option<RowCall>
index with these keys; None when there is no such action or a key
does not read as the key type.Source§fn key_json(&self, key: &str) -> Option<Value>
fn key_json(&self, key: &str) -> Option<Value>
None when it cannot be read.Source§fn page_keys(&self, page: &LoadedPage) -> Vec<Value>
fn page_keys(&self, page: &LoadedPage) -> Vec<Value>
Source§fn export_access(&self) -> Option<Access>
fn export_access(&self) -> Option<Access>
None when the grid offers no export.Source§fn export_limit(&self) -> usize
fn export_limit(&self) -> usize
Source§fn csv_head(&self, r: &Render<'_>, view: Option<&DataGridView>) -> String
fn csv_head(&self, r: &Render<'_>, view: Option<&DataGridView>) -> String
Source§fn csv_rows(&self, page: &LoadedPage, r: &Render<'_>) -> String
fn csv_rows(&self, page: &LoadedPage, r: &Render<'_>) -> String
Source§fn export_columns(
&self,
r: &Render<'_>,
view: Option<&DataGridView>,
) -> Vec<ExportColumn>
fn export_columns( &self, r: &Render<'_>, view: Option<&DataGridView>, ) -> Vec<ExportColumn>
Source§fn export_text(&self, page: &LoadedPage, r: &Render<'_>) -> Vec<Vec<String>>
fn export_text(&self, page: &LoadedPage, r: &Render<'_>) -> Vec<Vec<String>>
Source§fn export_values(&self, page: &LoadedPage, r: &Render<'_>) -> Vec<Vec<Value>>
fn export_values(&self, page: &LoadedPage, r: &Render<'_>) -> Vec<Vec<Value>>
Source§fn edit_call(
&self,
page: &LoadedPage,
key: &str,
values: &Map<String, Value>,
locale: &str,
tz: TimeZone,
) -> Result<RowCall>
fn edit_call( &self, page: &LoadedPage, key: &str, values: &Map<String, Value>, locale: &str, tz: TimeZone, ) -> Result<RowCall>
values, otherwise Forbidden; values are
read and validated as a form would (Validation errors name the fields).Source§fn row_html(
&self,
page: &LoadedPage,
key: &str,
r: &Render<'_>,
) -> Option<String>
fn row_html( &self, page: &LoadedPage, key: &str, r: &Render<'_>, ) -> Option<String>
Source§fn row_call(&self, page: &LoadedPage, key: &str, item: &str) -> Option<RowCall>
fn row_call(&self, page: &LoadedPage, key: &str, item: &str) -> Option<RowCall>
a0 for the first row action) from the loaded row with
this key. None when the row is not there or the item does not exist for it.fn fetch(&self, ctx: Ctx, query: DataQuery) -> BoxFuture<Result<LoadedPage>>
Source§fn fetch_at(
&self,
ctx: Ctx,
query: DataQuery,
path: Vec<Option<String>>,
) -> BoxFuture<Result<LoadedPage>>
fn fetch_at( &self, ctx: Ctx, query: DataQuery, path: Vec<Option<String>>, ) -> BoxFuture<Result<LoadedPage>>
path (group values or ancestor keys from the client, checked here). Flat grids ignore
path. Exports and bulk actions use GridSource::fetch, which never groups.Source§fn rows_html(&self, page: &LoadedPage, r: &Render<'_>) -> String
fn rows_html(&self, page: &LoadedPage, r: &Render<'_>) -> String
Source§fn render_loaded(&self, out: &mut String, r: &Render<'_>, page: &LoadedPage)
fn render_loaded(&self, out: &mut String, r: &Render<'_>, page: &LoadedPage)
Source§fn foot_html(&self, page: &LoadedPage, r: &Render<'_>) -> Option<String>
fn foot_html(&self, page: &LoadedPage, r: &Render<'_>) -> Option<String>
None when the grid has no totals or the
page carries none (the client keeps the footer it has).Source§fn fields(&self) -> &'static [FieldMeta]
fn fields(&self) -> &'static [FieldMeta]
Source§fn sensitive_model(&self) -> Option<&'static str>
fn sensitive_model(&self) -> Option<&'static str>
#[sensitive], so exports are audited.