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.class == other.class
31 && self.th_class == other.th_class
32 && self.show_sort_indicator == other.show_sort_indicator
33 }
34}
35
36#[function_component(TableHeader)]
38pub fn table_header<T: Clone + PartialEq + 'static>(props: &TableHeaderProps<T>) -> Html {
39 let column_ids = props.table.visible_column_ids();
41
42 html! {
43 <thead class={props.class.clone()}>
44 <tr>
45 {column_ids.iter().map(|column_id| {
46 let header = props.table.get_column_header(column_id).unwrap_or_default();
48 let is_sortable = props.table.is_column_sortable(column_id);
49 let sort_direction = props.table.get_sort_direction(column_id);
50 let sort_index = props.table.get_sort_index(column_id);
51
52 let onclick = {
54 let table = props.table.clone();
55 let column_id = column_id.clone();
56 Callback::from(move |e: MouseEvent| {
57 if is_sortable {
58 let multi = e.shift_key();
60 table.toggle_sort(column_id.clone(), multi);
61 }
62 })
63 };
64
65 let sort_indicator = if props.show_sort_indicator {
67 render_sort_indicator(sort_direction, sort_index)
68 } else {
69 html! {}
70 };
71
72 let cursor_class = if is_sortable { "cursor-pointer" } else { "" };
74
75 html! {
76 <th
77 key={column_id.as_str().to_string()}
78 class={classes!(props.th_class.clone(), cursor_class)}
79 onclick={onclick}
80 >
81 <div class="flex items-center gap-1">
82 <span>{header}</span>
83 {sort_indicator}
84 </div>
85 </th>
86 }
87 }).collect::<Html>()}
88 </tr>
89 </thead>
90 }
91}
92
93fn render_sort_indicator(direction: Option<SortDirection>, index: Option<usize>) -> Html {
104 match direction {
106 Some(SortDirection::Asc) => html! {
107 <span class="sort-indicator">
108 {"▲"}
109 {index.map(|i| html! { <sub>{i + 1}</sub> }).unwrap_or_default()}
110 </span>
111 },
112 Some(SortDirection::Desc) => html! {
113 <span class="sort-indicator">
114 {"▼"}
115 {index.map(|i| html! { <sub>{i + 1}</sub> }).unwrap_or_default()}
116 </span>
117 },
118 None => html! {},
119 }
120}