Skip to main content

DataTable

Function DataTable 

Source
pub fn DataTable(props: DataTableProps) -> impl IntoView
Expand description

Presents sortable, filterable tabular data with built-in toolbar, selection, and pagination.

Bind columns and items (or data_source) to get a working table. Enable advanced capabilities via DataTableFeatures and tune toolbar/header chrome with DataTableToolbarConfig and DataTableHeaderChromeConfig. For static HTML tables without a data engine, use Table instead.

§When to use

  • Interactive grids over medium client-side datasets with sort, search, and pagination
  • Server-driven paging, sort, and filter via DataTableSource::Server
  • Admin views that need selection, editing, export, or grouping

§When to use Table instead

Use Table for static or lightly interactive content without a built-in data engine.

§Usage

  1. Define columns with DataTableColumnDef — see Column Definition.
  2. Supply rows via items or data_source.
  3. Enable feature flags on features as needed (pinning, virtualization, pivot, etc.).
  4. Customize toolbar and header chrome with toolbar_config and header_chrome without replacing slots.

§Best Practices

§Do’s

§Don’ts

  • Do not replace the entire toolbar when you only need to hide one control — use toolbar_config
  • Do not use raw HTML for toolbar/footer controls — the built-in chrome uses Orbital primitives

§DataTable topic guide

§Toolbar and header chrome

FieldTypeDefaultDescription
quick_searchbooltrueQuick-search field in the toolbar
filter_panelbooltrueStructured filter panel trigger
column_pickerbooltrueColumn visibility picker trigger
pivotbooltruePivot panel trigger (requires PIVOTING)
export_menubooltrueExport/print menu trigger

DataTableHeaderChromeConfig gates per-header menu, filter button, and hide-column UX. See Column Features for header chrome interaction with column menus.

§Examples

§Default data table

Sortable columns with quick search and pagination.

use crate::{DataTable, DataTableColumnDef, DataTableRowModel};
use std::collections::HashMap;
let items = RwSignal::new(vec![
    DataTableRowModel::from_text_cells("1", HashMap::from([("name".into(), "Ada".into()), ("role".into(), "Admin".into())])),
    DataTableRowModel::from_text_cells("2", HashMap::from([("name".into(), "Grace".into()), ("role".into(), "Editor".into())])),
]);
view! {
    <div data-testid="data-table-preview">
        <DataTable
            sortable=true
            columns=vec![
                DataTableColumnDef::new("name", "Name"),
                DataTableColumnDef::new("role", "Role"),
            ]
            items=items
        />
    </div>
}

§Row selection

Multiselect with checkboxes.

use crate::{DataTable, DataTableColumnDef, DataTableRowModel, DataTableSelectionMode};
use std::collections::HashMap;
let items = RwSignal::new(vec![
    DataTableRowModel::from_text_cells("a", HashMap::from([("name".into(), "Alpha".into())])),
    DataTableRowModel::from_text_cells("b", HashMap::from([("name".into(), "Beta".into())])),
]);
view! {
    <div data-testid="data-table-selection">
        <DataTable
            selection_mode=DataTableSelectionMode::Multiselect
            columns=vec![DataTableColumnDef::new("name", "Name")]
            items=items
        />
    </div>
}

§Density variants

Row and header heights respond to theme density.

use crate::{DataTable, DataTableColumnDef, DataTableRowModel};
use orbital_core_components::{Flex, FlexGap, ThemeDensityStepper};
use std::collections::HashMap;
let items = RwSignal::new(vec![
    DataTableRowModel::from_text_cells("1", HashMap::from([("name".into(), "Ada".into())])),
]);
view! {
    <div data-testid="data-table-density">
        <Flex vertical=true gap=FlexGap::Medium>
            <ThemeDensityStepper />
            <DataTable
                columns=vec![DataTableColumnDef::new("name", "Name")]
                items=items
            />
        </Flex>
    </div>
}

§Layout

Fixed height and flex-fill in a bounded parent.

use std::collections::HashMap;
use crate::{DataTable, DataTableColumnDef, DataTableRowModel, PagingMode};
let items = RwSignal::new((0..30).map(|i| {
    DataTableRowModel::from_text_cells(&i.to_string(), HashMap::from([("name".into(), format!("Row {i}"))]))
}).collect::<Vec<_>>());
view! {
    <div data-testid="data-table-layout-preview" style="display: flex; flex-direction: column; height: 350px;">
        <DataTable
            flex=true
            max_height=280.0
            paging=PagingMode::None
            columns=vec![DataTableColumnDef::new("name", "Name")]
            items=items
        />
    </div>
}

§Custom slots

Replace toolbar, footer, and empty views with custom content via Leptos slot children.

use std::collections::HashMap;
use crate::{
    DataTable, DataTableColumnDef, DataTableEmptyView, DataTableFooterSlot,
    DataTableRowModel, DataTableToolbarSlot, PagingMode,
};
use orbital_core_components::{Toolbar, ToolbarButton};
let empty: RwSignal<Vec<DataTableRowModel>> = RwSignal::new(vec![]);
view! {
    <div data-testid="data-table-slots-preview">
        <DataTable
            paging=PagingMode::None
            max_height=200.0
            columns=vec![DataTableColumnDef::new("name", "Name")]
            items=empty
        >
            <DataTableToolbarSlot slot>
                <div data-testid="custom-toolbar">
                    <Toolbar><ToolbarButton>"Custom toolbar"</ToolbarButton></Toolbar>
                </div>
            </DataTableToolbarSlot>
            <DataTableFooterSlot slot>
                <div data-testid="custom-footer">"Custom footer"</div>
            </DataTableFooterSlot>
            <DataTableEmptyView slot>
                <div data-testid="custom-empty">"No data yet"</div>
            </DataTableEmptyView>
        </DataTable>
    </div>
}

§Toolbar and header chrome

Toggle built-in toolbar controls and column-header actions without replacing the whole toolbar.

use std::collections::HashMap;
use crate::{
    DataTable, DataTableColumnDef, DataTableHeaderChromeConfig, DataTableRowModel,
    DataTableToolbarConfig, PagingMode,
};
let items = RwSignal::new(vec![
    DataTableRowModel::from_text_cells("1", HashMap::from([("name".into(), "Ada".into())])),
]);
view! {
    <div data-testid="data-table-chrome-config-preview">
        <DataTable
            paging=PagingMode::None
            max_height=200.0
            toolbar_config=DataTableToolbarConfig {
                quick_search: true,
                filter_panel: false,
                column_picker: false,
                pivot: false,
                export_menu: true,
            }
            header_chrome=DataTableHeaderChromeConfig {
                column_menu: false,
                column_filter_button: false,
                column_hide: false,
            }
            columns=vec![DataTableColumnDef::new("name", "Name")]
            items=items
        />
    </div>
}

§Optional Props