table_rs/yew/
body.rs

1use crate::yew::types::TableBodyProps;
2use yew::prelude::*;
3
4/// A table body component that handles rendering of table rows, empty state, and loading state.
5///
6/// This component is part of the `table_rs` Yew integration and is responsible for rendering
7/// the `<tbody>` section of a table, based on the provided data and configuration.
8///
9/// # Arguments
10/// * `props` - The properties passed to the component.
11///   - `columns` - A list of column definitions (`Vec<Column>`) specifying which fields to render.
12///   - `rows` - A vector of row data (`Vec<HashMap<&'static str, String>>`) to display.
13///   - `loading` - A boolean flag indicating whether the table is in a loading state.
14///   - `classes` - A `TableClasses` object defining CSS class names for customization.
15///   - `texts` - A `TableTexts` object defining UI text like loading or empty messages.
16///
17/// # Returns
18/// (Html): A rendered `<tbody>` element, containing:
19///   - A loading row if `loading` is `true`.
20///   - An empty state row if `rows` is empty.
21///   - The list of rows otherwise.
22///
23/// # Examples
24/// ```rust
25/// use table_rs::yew::body::TableBody;
26/// use table_rs::yew::types::{TableBodyProps, Column, TableClasses, TableTexts};
27/// use yew::prelude::*;
28/// use maplit::hashmap;
29///
30/// #[function_component(App)]
31/// pub fn app() -> Html {
32///     let rows = vec![
33///         hashmap! { "name" => "Ferris".to_string(), "email" => "ferris@opensass.org".to_string() },
34///         hashmap! { "name" => "Crab".to_string(), "email" => "crab@opensass.org".to_string() },
35///     ];
36///    
37///     let columns = vec![
38///         Column { id: "name", header: "Name", ..Default::default() },
39///         Column { id: "email", header: "Email", ..Default::default() },
40///     ];
41///    
42///     let props = TableBodyProps {
43///         columns,
44///         rows,
45///         loading: false,
46///         classes: Default::default(),
47///         texts: Default::default(),
48///     };
49///    
50///     html! {
51///         <TableBody ..props />
52///     }
53/// }
54/// ```
55///
56/// # See Also
57/// - [MDN tbody Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/tbody)
58#[function_component(TableBody)]
59pub fn body(props: &TableBodyProps) -> Html {
60    let TableBodyProps {
61        columns,
62        rows,
63        loading,
64        classes,
65        texts,
66    } = props;
67
68    html! {
69        <tbody class={classes.tbody}>
70            { if *loading {
71                    html! {
72                        <tr class={classes.loading_row}><td colspan={columns.len().to_string()}>{ texts.loading }</td></tr>
73                    }
74                } else if rows.is_empty() {
75                    html! {
76                        <tr class={classes.empty_row}><td colspan={columns.len().to_string()}>{ texts.empty }</td></tr>
77                    }
78                } else {
79                    html! {
80                        for row in rows.iter() {
81                                <tr class={classes.row} role="row">
82                                        for col in columns.iter() {
83                                                <td class={classes.body_cell} role="cell">{ row.get(col.id).unwrap_or(&"".to_string()) }</td>
84                                        }
85                                </tr>
86                        }
87                    }
88                } }
89        </tbody>
90    }
91}