From 00317f10bcb67bf8a154a9b51691830149d6f2b7 Mon Sep 17 00:00:00 2001 From: Ronny Bremer Date: Wed, 26 Nov 2025 12:34:03 +0100 Subject: [PATCH 1/7] added missing feature Location to web-sys dependency --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ef18c11..e4daff5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ exclude = ["/assets", "/examples"] yew = { version = "0.21.0", default-features = false, optional = true } dioxus = { version = "0.7.1", optional = true } leptos = { version = "0.7.7", optional = true } -web-sys = { version = "0.3.77", features = ["Window", "UrlSearchParams", "Url"]} +web-sys = { version = "0.3.77", features = ["Window", "UrlSearchParams", "Url", "Location"]} gloo-timers = { version = "0.3.0", optional = true } [features] From f79692d4ba5cdd4b6c6b0457bdb8f21ccf87c5ec Mon Sep 17 00:00:00 2001 From: Ronny Bremer Date: Wed, 26 Nov 2025 12:39:37 +0100 Subject: [PATCH 2/7] added feature History to web-sys dependency --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e4daff5..1c97032 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ exclude = ["/assets", "/examples"] yew = { version = "0.21.0", default-features = false, optional = true } dioxus = { version = "0.7.1", optional = true } leptos = { version = "0.7.7", optional = true } -web-sys = { version = "0.3.77", features = ["Window", "UrlSearchParams", "Url", "Location"]} +web-sys = { version = "0.3.77", features = ["Window", "UrlSearchParams", "Url", "Location", "History"]} gloo-timers = { version = "0.3.0", optional = true } [features] From c4b948f7dbfb318eda0a1e5a034b837c689057d6 Mon Sep 17 00:00:00 2001 From: Ronny Bremer Date: Wed, 26 Nov 2025 15:34:49 +0100 Subject: [PATCH 3/7] URL handling for wasm targets only --- src/dioxus/table.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dioxus/table.rs b/src/dioxus/table.rs index 48a6bf9..3d1cd9e 100644 --- a/src/dioxus/table.rs +++ b/src/dioxus/table.rs @@ -85,6 +85,7 @@ pub fn Table(props: TableProps) -> Element { let mut sort_order = use_signal(SortOrder::default); let mut search_query = use_signal(String::new); + #[cfg(target_arch = "wasm")] use_effect(move || { let window = web_sys::window().unwrap(); let location = window.location(); @@ -95,6 +96,7 @@ pub fn Table(props: TableProps) -> Element { } }); + #[cfg(target_arch = "wasm")] let update_search_param = move |query: &str| { let window = web_sys::window().unwrap(); let href = window.location().href().unwrap(); @@ -182,6 +184,7 @@ pub fn Table(props: TableProps) -> Element { let val = e.value(); search_query.set(val.clone()); page.set(0); + #[cfg(target_arch = "wasm")] update_search_param(&val); } } From c780d4416c83030058598df5eb8a82e33b7d4259 Mon Sep 17 00:00:00 2001 From: Ronny Bremer Date: Fri, 28 Nov 2025 12:34:18 +0100 Subject: [PATCH 4/7] replaced cfg condition with recommendation from the Rust Cookbook --- src/dioxus/table.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dioxus/table.rs b/src/dioxus/table.rs index 3d1cd9e..45837d1 100644 --- a/src/dioxus/table.rs +++ b/src/dioxus/table.rs @@ -85,7 +85,7 @@ pub fn Table(props: TableProps) -> Element { let mut sort_order = use_signal(SortOrder::default); let mut search_query = use_signal(String::new); - #[cfg(target_arch = "wasm")] + #[cfg(target_family = "wasm")] use_effect(move || { let window = web_sys::window().unwrap(); let location = window.location(); @@ -96,7 +96,7 @@ pub fn Table(props: TableProps) -> Element { } }); - #[cfg(target_arch = "wasm")] + #[cfg(target_family = "wasm")] let update_search_param = move |query: &str| { let window = web_sys::window().unwrap(); let href = window.location().href().unwrap(); From 927ca7bbca03bb6d686a08a9ba905e051756efc7 Mon Sep 17 00:00:00 2001 From: Ronny Bremer Date: Sat, 29 Nov 2025 14:51:01 +0100 Subject: [PATCH 5/7] fixed incorrect conditional compile statement --- src/dioxus/table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dioxus/table.rs b/src/dioxus/table.rs index 45837d1..fe213c7 100644 --- a/src/dioxus/table.rs +++ b/src/dioxus/table.rs @@ -184,7 +184,7 @@ pub fn Table(props: TableProps) -> Element { let val = e.value(); search_query.set(val.clone()); page.set(0); - #[cfg(target_arch = "wasm")] + #[cfg(target_family = "wasm")] update_search_param(&val); } } From 4251dc795c62145b653298c5b773b91c33d2cbd5 Mon Sep 17 00:00:00 2001 From: Ronny Bremer Date: Sun, 22 Mar 2026 15:15:00 +0100 Subject: [PATCH 6/7] - added coptional allback to handle clicking on a row - added default sort column prop --- src/dioxus/body.rs | 37 +++++++++++++++++++++---------------- src/dioxus/table.rs | 36 ++++++++++++++++++++---------------- src/dioxus/types.rs | 17 +++++++++++++++++ 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/dioxus/body.rs b/src/dioxus/body.rs index f0003eb..5009f1a 100644 --- a/src/dioxus/body.rs +++ b/src/dioxus/body.rs @@ -15,6 +15,7 @@ use std::collections::HashMap; /// - `loading`: A `bool` flag that, when true, displays a loading message instead of data rows. /// - `classes`: A `TableClasses` struct for customizing the CSS class names of the body, rows, and cells. /// - `texts`: A `TableTexts` struct that provides custom text for the loading and empty states. +/// - `on_column_click`: An optional callback when a row is clicked. /// /// # Behavior /// - If `loading` is `true`, a single row with a loading message is shown spanning all columns. @@ -65,31 +66,39 @@ pub fn TableBody( loading: bool, classes: TableClasses, texts: TableTexts, + on_column_click: Option>>, ) -> Element { let content = if loading { rsx! { tr { class: "{classes.loading_row}", - td { - colspan: "{columns.len()}", - "{texts.loading}" - } + td { colspan: "{columns.len()}", "{texts.loading}" } } } } else if rows.is_empty() { rsx! { tr { class: "{classes.empty_row}", - td { - colspan: "{columns.len()}", - "{texts.empty}" - } + td { colspan: "{columns.len()}", "{texts.empty}" } } } } else { rsx! { for row in rows.iter() { - tr { class: "{classes.row}", role: "row", + tr { + class: "{classes.row}", + role: "row", + onclick: { + let row1 = row.clone(); + move |_| { + if let Some(on_column_click) = on_column_click { + on_column_click.call(row1.clone()); + } + } + }, for col in columns.iter() { - td { class: "{classes.body_cell}", role: "cell", + td { + class: "{classes.body_cell} {col.cell_class.unwrap_or_default()}", + style: "{col.cell_style.unwrap_or_default()}", + role: "cell", BodyCell { column: col.clone(), content: row.get(col.id).unwrap_or(&String::new()), @@ -102,9 +111,7 @@ pub fn TableBody( }; rsx! { - tbody { class: "{classes.tbody}", - {content} - } + tbody { class: "{classes.tbody}", {content} } } } @@ -113,8 +120,6 @@ fn BodyCell(column: Column, content: String) -> Element { if let Some(cb) = column.cell { cb(content) } else { - rsx! { - "{content}" - } + rsx! { "{content}" } } } diff --git a/src/dioxus/table.rs b/src/dioxus/table.rs index fe213c7..b3a63be 100644 --- a/src/dioxus/table.rs +++ b/src/dioxus/table.rs @@ -78,10 +78,12 @@ pub fn Table(props: TableProps) -> Element { search, texts, classes, + default_sort_column, + on_column_click, } = props; let mut page = use_signal(|| 0_usize); - let mut sort_column = use_signal(|| None::<&'static str>); + let mut sort_column = use_signal(|| default_sort_column); let mut sort_order = use_signal(SortOrder::default); let mut search_query = use_signal(String::new); @@ -146,12 +148,15 @@ pub fn Table(props: TableProps) -> Element { let end = ((page() + 1) * page_size).min(filtered_rows.len()); let page_rows = &filtered_rows[start..end]; + // if this is the first click on a header column, sort ASC + // on second cick sort DESC + // on third click don't sort anymore let on_sort_column = move |id: &'static str| { if Some(id) == sort_column() { - sort_order.set(match sort_order() { - SortOrder::Asc => SortOrder::Desc, - SortOrder::Desc => SortOrder::Asc, - }); + match sort_order() { + SortOrder::Asc => sort_order.set(SortOrder::Desc), + SortOrder::Desc => sort_column.set(None), + } } else { sort_column.set(Some(id)); sort_order.set(SortOrder::Asc); @@ -161,8 +166,8 @@ pub fn Table(props: TableProps) -> Element { let pagination_controls = if paginate { rsx! { PaginationControls { - page: page, - total_pages: total_pages, + page, + total_pages, classes: classes.clone(), texts: texts.clone(), } @@ -172,8 +177,7 @@ pub fn Table(props: TableProps) -> Element { }; rsx! { - div { - class: "{classes.container}", + div { class: "{classes.container}", if search { input { class: "{classes.search_input}", @@ -186,24 +190,24 @@ pub fn Table(props: TableProps) -> Element { page.set(0); #[cfg(target_family = "wasm")] update_search_param(&val); - } + }, } } - table { - class: "{classes.table}", + table { class: "{classes.table}", TableHeader { columns: columns.clone(), - sort_column: sort_column, - sort_order: sort_order, - on_sort_column: on_sort_column, + sort_column, + sort_order, + on_sort_column, classes: classes.clone(), } TableBody { columns: columns.clone(), rows: page_rows.to_vec(), - loading: loading, + loading, classes: classes.clone(), texts: texts.clone(), + on_column_click, } } {pagination_controls} diff --git a/src/dioxus/types.rs b/src/dioxus/types.rs index 43a71d5..e3a05d9 100644 --- a/src/dioxus/types.rs +++ b/src/dioxus/types.rs @@ -29,6 +29,14 @@ pub struct Column { /// Optional CSS classes for the column header. #[props(default)] pub class: Option<&'static str>, + + /// Optional inline styles for the column cell. + #[props(default)] + pub cell_style: Option<&'static str>, + + /// Optional CSS classes for the column cell. + #[props(default)] + pub cell_class: Option<&'static str>, } /// Text labels for table UI elements. @@ -165,6 +173,15 @@ pub struct TableProps { /// CSS classes for styling different parts of the table. #[props(default)] pub classes: TableClasses, + + /// Default sort column when the table is initially rendered + #[props(default)] + pub default_sort_column: Option<&'static str>, + + /// optional event handler when a column has been clicked + /// will pass in the content of the column + #[props(default)] + pub on_column_click: Option>>, } /// Sort direction (ascending or descending). From 189da6deaa0df47cd2c2dd7a1f8bcbc5804279be Mon Sep 17 00:00:00 2001 From: Ronny Bremer Date: Sun, 22 Mar 2026 15:39:10 +0100 Subject: [PATCH 7/7] fixed unused warnings for non-wasm builds --- src/dioxus/table.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dioxus/table.rs b/src/dioxus/table.rs index b3a63be..9b87576 100644 --- a/src/dioxus/table.rs +++ b/src/dioxus/table.rs @@ -1,5 +1,7 @@ use dioxus::prelude::*; +#[cfg(target_family = "wasm")] use web_sys::UrlSearchParams; +#[cfg(target_family = "wasm")] use web_sys::wasm_bindgen::JsValue; use crate::dioxus::body::TableBody;