From: Dominik Csapak <d.csapak@proxmox.com>
To: yew-devel@lists.proxmox.com
Subject: [PATCH yew-widget-toolkit v4 1/2] widget: data table: factor out cell rendering logic
Date: Thu, 15 Oct 2026 14:38:27 +0200 [thread overview]
Message-ID: <20261015124047.3536357-2-d.csapak@proxmox.com> (raw)
In-Reply-To: <20261015124047.3536357-1-d.csapak@proxmox.com>
Move the loop that renders the visible cells of a row, including the
colspan handling, into a separate function, so that it can be reused for
rendering invisible sample rows to size the columns.
No functional change intended.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/widget/data_table/mod.rs | 3 ++
src/widget/data_table/rendered_cell.rs | 59 +++++++++++++++++++++++
src/widget/data_table/row.rs | 66 +++++++++-----------------
3 files changed, 84 insertions(+), 44 deletions(-)
create mode 100644 src/widget/data_table/rendered_cell.rs
diff --git a/src/widget/data_table/mod.rs b/src/widget/data_table/mod.rs
index 2ab03b6..ba0d0ff 100644
--- a/src/widget/data_table/mod.rs
+++ b/src/widget/data_table/mod.rs
@@ -29,6 +29,9 @@ pub use cell_configuration::CellConfiguration;
mod cell_render_callback;
pub use cell_render_callback::{DataTableCellRenderArgs, DataTableCellRenderer};
+mod rendered_cell;
+pub(crate) use rendered_cell::render_row_cells;
+
mod header_render_callback;
pub use header_render_callback::{
DataTableHeaderRenderArgs, DataTableHeaderRenderer, DataTableHeaderTableLink,
diff --git a/src/widget/data_table/rendered_cell.rs b/src/widget/data_table/rendered_cell.rs
new file mode 100644
index 0000000..42ab8e6
--- /dev/null
+++ b/src/widget/data_table/rendered_cell.rs
@@ -0,0 +1,59 @@
+use yew::Html;
+
+use crate::widget::data_table::{CellConfiguration, DataTableCellRenderArgs, DataTableColumn};
+
+/// Contains the rendered cell contents plus meta info to properly show it in the data table
+pub(crate) struct RenderedCell<'a, T: 'static> {
+ pub column_num: usize,
+ pub config: CellConfiguration,
+ pub content: Html,
+ pub column: &'a DataTableColumn<T>,
+}
+
+/// Calculates the necessary index and colspan properties and renders the cell for a row.
+pub(crate) fn render_row_cells<'a, T>(
+ columns: &'a [DataTableColumn<T>],
+ columns_hidden: &[bool],
+ mut make_args: impl FnMut(usize) -> DataTableCellRenderArgs<'a, T>,
+) -> Vec<RenderedCell<'a, T>> {
+ let mut res = Vec::with_capacity(columns.len());
+
+ let mut col_index = 0;
+ let mut column_num = 0;
+
+ while let Some(column) = columns.get(column_num) {
+ if let Some(true) = columns_hidden.get(column_num) {
+ column_num += 1;
+ continue;
+ }
+
+ let mut args = make_args(col_index);
+
+ let content = column.apply_render(&mut args);
+
+ let mut colspan = 1;
+
+ for (attr_name, attr_value) in args.config.attributes.iter() {
+ if attr_name != "colspan" {
+ continue;
+ }
+
+ match attr_value.parse::<usize>() {
+ Ok(n) if n > 0 => colspan = n,
+ _ => {}
+ }
+ }
+
+ res.push(RenderedCell {
+ column_num,
+ config: args.config,
+ content,
+ column,
+ });
+
+ col_index += colspan;
+ column_num += colspan;
+ }
+
+ res
+}
diff --git a/src/widget/data_table/row.rs b/src/widget/data_table/row.rs
index 34bbbdf..9ce1f4d 100644
--- a/src/widget/data_table/row.rs
+++ b/src/widget/data_table/row.rs
@@ -13,7 +13,7 @@ use crate::widget::Container;
use super::{
CellConfiguration, DataTableCellRenderArgs, DataTableColumn, DataTableRowRenderArgs,
- DataTableRowRenderCallback,
+ DataTableRowRenderCallback, render_row_cells,
};
/// DataTable row properties.
@@ -119,15 +119,23 @@ impl<T: Clone + PartialEq + 'static> Component for PwtDataTableRow<T> {
let minheight_cell_style =
AttrValue::Rc(format!("vertical-align:top;height: {}px;", props.min_row_height).into());
- let mut col_index = 0;
- let mut column_num = 0;
-
- while let Some(column) = props.columns.get(column_num) {
- if let Some(true) = props.column_hidden.get(column_num) {
- column_num += 1;
- continue;
+ let rendered_cells = render_row_cells(&props.columns, &props.column_hidden, |col_index| {
+ DataTableCellRenderArgs {
+ selection: props.selection.clone(),
+ record: &props.record,
+ record_key: &props.record_key,
+ row_index: props.row_num,
+ column_index: col_index,
+ selected: props.selected,
+ config: (*props.cell_config).clone(),
+ is_expanded: props.is_expanded,
+ is_leaf: props.is_leaf,
+ level: props.level,
}
+ });
+ for cell in rendered_cells {
+ let column = cell.column;
let vertical_align = props
.vertical_align
.to_owned()
@@ -136,52 +144,22 @@ impl<T: Clone + PartialEq + 'static> Component for PwtDataTableRow<T> {
let text_align = column.justify.to_owned();
let cell_active = match props.active_cell {
- Some(active_cell) => active_cell == column_num,
+ Some(active_cell) => active_cell == cell.column_num,
None => false,
};
- let mut args = DataTableCellRenderArgs {
- selection: props.selection.clone(),
- record: &props.record,
- record_key: &props.record_key,
- row_index: props.row_num,
- column_index: col_index,
- selected: props.selected,
- config: (*props.cell_config).clone(),
- is_expanded: props.is_expanded,
- is_leaf: props.is_leaf,
- level: props.level,
- };
-
- let cell = column.apply_render(&mut args);
-
let mut td = Container::from_tag("td")
- .class(args.config.class)
+ .class(cell.config.class)
.class((cell_active && props.has_focus).then_some("cell-cursor"))
- .styles(args.config.style)
+ .styles(cell.config.style)
.style("vertical-align", vertical_align)
.style("text-align", text_align)
.attribute("role", "gridcell")
- .attribute("data-column-num", column_num.to_string())
+ .attribute("data-column-num", cell.column_num.to_string())
.attribute("tabindex", if cell_active { "0" } else { "-1" })
- .with_child(html! {<div role="none">{cell}</div>});
-
- let mut colspan = 1;
-
- for (attr_name, attr_value) in args.config.attributes.iter() {
- if attr_name == "colspan" {
- if let Ok(n) = attr_value.parse::<usize>() {
- if n > 0 {
- colspan = n
- }
- }
- }
- }
-
- td.as_std_props_mut().add_attributes(args.config.attributes);
+ .with_child(html! {<div role="none">{cell.content}</div>});
- col_index += colspan;
- column_num += colspan;
+ td.as_std_props_mut().add_attributes(cell.config.attributes);
row.add_child(td);
}
--
2.47.3
next prev parent reply other threads:[~2026-10-15 12:40 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 12:38 [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dominik Csapak
2026-10-15 12:38 ` Dominik Csapak [this message]
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 2/2] widget: data table: implement auto column sizing based on sample records Dominik Csapak
2026-10-16 7:42 ` [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261015124047.3536357-2-d.csapak@proxmox.com \
--to=d.csapak@proxmox.com \
--cc=yew-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox