yew_datatable/components/
table_header.rs1use crate::hooks::use_table::UseTableHandle;
4use yew::prelude::*;
5use yew_datatable_core::prelude::SortDirection;
6
7#[derive(Properties, Clone)]
9pub struct TableHeaderProps<T: Clone + PartialEq + 'static> {
10 pub table: UseTableHandle<T>,
12
13 #[prop_or_default]
15 pub class: Classes,
16
17 #[prop_or_default]
19 pub th_class: Classes,
20
21 #[prop_or(true)]
23 pub show_sort_indicator: bool,
24}
25
26impl<T: Clone + PartialEq + 'static> PartialEq for TableHeaderProps<T> {
28 fn eq(&self, other: &Self) -> bool {
29 self.table == other.table
31 && self.class == other.class
33 && self.th_class == other.th_class
34 && self.show_sort_indicator == other.show_sort_indicator
35 }
36}
37
38#[function_component(TableHeader)]
40pub fn table_header<T: Clone + PartialEq + 'static>(props: &TableHeaderProps<T>) -> Html {
41 let column_ids = props.table.visible_column_ids();
43
44 html! {
45 <thead class={props.class.clone()}>
46 <tr>
47 {column_ids.iter().map(|column_id| {
48 let header = props.table.get_column_header(column_id).unwrap_or_default();
50 let is_sortable = props.table.is_column_sortable(column_id);
51 let sort_direction = props.table.get_sort_direction(column_id);
52 let sort_index = props.table.get_sort_index(column_id);
53
54 let onclick = {
56 let table = props.table.clone();
57 let column_id = column_id.clone();
58 Callback::from(move |e: MouseEvent| {
59 if is_sortable {
60 let multi = e.shift_key();
62 table.toggle_sort(column_id.clone(), multi);
63 }
64 })
65 };
66
67 let sort_indicator = if props.show_sort_indicator {
69 render_sort_indicator(sort_direction, sort_index)
70 } else {
71 html! {}
72 };
73
74 let cursor_class = if is_sortable { "cursor-pointer" } else { "" };
76
77 html! {
78 <th
79 key={column_id.as_str().to_string()}
80 class={classes!(props.th_class.clone(), cursor_class)}
81 onclick={onclick}
82 >
83 <div class="flex items-center gap-1">
84 <span>{header}</span>
85 {sort_indicator}
86 </div>
87 </th>
88 }
89 }).collect::<Html>()}
90 </tr>
91 </thead>
92 }
93}
94
95fn render_sort_indicator(direction: Option<SortDirection>, index: Option<usize>) -> Html {
106 match direction {
108 Some(SortDirection::Asc) => html! {
109 <span class="sort-indicator">
110 {"▲"}
111 {index.map(|i| html! { <sub>{i + 1}</sub> }).unwrap_or_default()}
112 </span>
113 },
114 Some(SortDirection::Desc) => html! {
115 <span class="sort-indicator">
116 {"▼"}
117 {index.map(|i| html! { <sub>{i + 1}</sub> }).unwrap_or_default()}
118 </span>
119 },
120 None => html! {},
121 }
122}