yew_datatable/hooks/
use_table.rs1use std::cell::RefCell;
4use std::rc::Rc;
5use yew::prelude::*;
6use yew_datatable_core::prelude::{
7 ColumnDef, ColumnId, DataTable, DataTableOptions, DataTableRow, DataTableRowId, DataTableState, SortDirection,
8};
9
10#[derive(Clone)]
12pub struct UseTableHandle<T: Clone + 'static> {
13 table: Rc<RefCell<DataTable<T>>>,
14 state: UseStateHandle<DataTableState>,
15 trigger: UseStateHandle<u32>,
16 data_version: Rc<RefCell<u32>>,
17}
18
19impl<T: Clone + 'static> PartialEq for UseTableHandle<T> {
20 fn eq(&self, other: &Self) -> bool {
21 *self.trigger == *other.trigger
23 && *self.data_version.borrow() == *other.data_version.borrow()
24 && Rc::ptr_eq(&self.table, &other.table)
25 }
26}
27
28impl<T: Clone + 'static> UseTableHandle<T> {
29 pub fn visible_rows(&self) -> Vec<DataTableRow<T>> {
31 self.table.borrow().visible_rows().cloned().collect()
32 }
33
34 pub fn visible_column_ids(&self) -> Vec<ColumnId> {
36 self.table.borrow().visible_column_ids()
37 }
38
39 pub fn visible_columns(&self) -> Vec<ColumnId> {
41 self.table.borrow().visible_column_ids()
42 }
43
44 pub fn get_column_header(&self, id: &ColumnId) -> Option<String> {
46 self.table.borrow().get_column(id).map(|c| c.header().to_string())
47 }
48
49 pub fn is_column_sortable(&self, id: &ColumnId) -> bool {
51 self.table
52 .borrow()
53 .get_column(id)
54 .map(|c| c.is_sortable())
55 .unwrap_or(false)
56 }
57
58 pub fn get_cell_value(&self, row: &T, column_id: &ColumnId) -> Option<String> {
60 self.table
61 .borrow()
62 .get_column(column_id)
63 .and_then(|col| col.get_value(row))
64 .map(|v| v.as_string())
65 }
66
67 pub fn total_row_count(&self) -> usize {
69 self.table.borrow().total_row_count()
70 }
71
72 pub fn filtered_row_count(&self) -> usize {
74 self.table.borrow().filtered_row_count()
75 }
76
77 pub fn page_row_count(&self) -> usize {
79 self.table.borrow().page_row_count()
80 }
81
82 pub fn state(&self) -> DataTableState {
84 (*self.state).clone()
85 }
86
87 fn update(&self) {
89 self.state.set(self.table.borrow().state().clone());
90 self.trigger.set(*self.trigger + 1);
91 }
92
93 pub fn toggle_sort(&self, column_id: impl Into<ColumnId>, multi: bool) {
95 {
96 let mut table = self.table.borrow_mut();
97 table.toggle_sort(column_id, multi);
98 table.process();
99 }
100 self.update();
101 }
102
103 pub fn set_column_filter(&self, column_id: impl Into<ColumnId>, value: impl Into<String>) {
105 {
106 let mut table = self.table.borrow_mut();
107 table.set_column_filter(column_id, value);
108 table.process();
109 }
110 self.update();
111 }
112
113 pub fn set_global_filter(&self, value: impl Into<String>) {
115 {
116 let mut table = self.table.borrow_mut();
117 table.set_global_filter(value);
118 table.process();
119 }
120 self.update();
121 }
122
123 pub fn toggle_row_selection(&self, row_id: DataTableRowId) {
125 self.table.borrow_mut().toggle_row_selection(row_id);
126 self.update();
127 }
128
129 pub fn select_all_rows(&self) {
131 self.table.borrow_mut().select_all_rows();
132 self.update();
133 }
134
135 pub fn clear_selection(&self) {
137 self.table.borrow_mut().clear_selection();
138 self.update();
139 }
140
141 pub fn toggle_row_expansion(&self, row_id: DataTableRowId) {
143 {
144 let mut table = self.table.borrow_mut();
145 table.toggle_row_expansion(row_id);
146 table.process();
147 }
148 self.update();
149 }
150
151 pub fn toggle_column_visibility(&self, column_id: ColumnId) {
153 self.table.borrow_mut().toggle_column_visibility(column_id);
154 self.update();
155 }
156
157 pub fn go_to_page(&self, page: usize) {
159 {
160 let mut table = self.table.borrow_mut();
161 table.go_to_page(page);
162 table.process();
163 }
164 self.update();
165 }
166
167 pub fn next_page(&self) {
169 {
170 let mut table = self.table.borrow_mut();
171 table.next_page();
172 table.process();
173 }
174 self.update();
175 }
176
177 pub fn previous_page(&self) {
179 {
180 let mut table = self.table.borrow_mut();
181 table.previous_page();
182 table.process();
183 }
184 self.update();
185 }
186
187 pub fn set_page_size(&self, size: usize) {
189 {
190 let mut table = self.table.borrow_mut();
191 table.set_page_size(size);
192 table.process();
193 }
194 self.update();
195 }
196
197 pub fn reset(&self) {
199 {
200 let mut table = self.table.borrow_mut();
201 table.reset();
202 table.process();
203 }
204 self.update();
205 }
206
207 pub fn is_row_selected(&self, row_id: &DataTableRowId) -> bool {
209 self.table.borrow().state().row_selection.is_selected(row_id)
210 }
211
212 pub fn is_row_expanded(&self, row_id: &DataTableRowId) -> bool {
214 self.table.borrow().state().expanding.is_expanded(row_id)
215 }
216
217 pub fn is_column_visible(&self, column_id: &ColumnId) -> bool {
219 self.table.borrow().state().column_visibility.is_visible(column_id)
220 }
221
222 pub fn current_page(&self) -> usize {
224 self.table.borrow().state().pagination.page_index()
225 }
226
227 pub fn page_size(&self) -> usize {
229 self.table.borrow().state().pagination.page_size()
230 }
231
232 pub fn page_count(&self) -> usize {
234 let table = self.table.borrow();
235 table.state().pagination.page_count(table.filtered_row_count())
236 }
237
238 pub fn can_previous_page(&self) -> bool {
240 self.table.borrow().state().pagination.can_go_previous()
241 }
242
243 pub fn can_next_page(&self) -> bool {
245 let table = self.table.borrow();
246 table.state().pagination.can_go_next(table.filtered_row_count())
247 }
248
249 pub fn get_sort_direction(&self, column_id: &ColumnId) -> Option<SortDirection> {
251 self.table.borrow().state().sorting.get_direction(column_id)
252 }
253
254 pub fn get_sort_index(&self, column_id: &ColumnId) -> Option<usize> {
256 self.table.borrow().state().sorting.get_sort_index(column_id)
257 }
258
259 pub fn set_data(&self, data: Vec<T>) {
261 {
263 let mut table = self.table.borrow_mut();
264 table.set_data_indexed(data);
265 table.process();
266 }
267 *self.data_version.borrow_mut() += 1;
269 self.update();
271 }
272
273 pub fn data_version(&self) -> u32 {
275 *self.data_version.borrow()
276 }
277}
278
279#[hook]
291pub fn use_table<T: Clone + PartialEq + 'static>(
292 columns: Vec<ColumnDef<T>>,
293 data: Vec<T>,
294 _options: Option<DataTableOptions>,
295) -> UseTableHandle<T> {
296 let incoming_data = data;
298
299 let initial_data = incoming_data.clone();
301
302 let table_ref: Rc<RefCell<DataTable<T>>> = use_mut_ref(|| {
304 let mut t = DataTable::with_data(columns, initial_data, |_, idx| DataTableRowId::from_index(idx));
305 t.process();
306 t
307 });
308
309 let last_prop_data: Rc<RefCell<Vec<T>>> = use_mut_ref(|| incoming_data.clone());
311
312 let data_version: Rc<RefCell<u32>> = use_mut_ref(|| 0);
313 let state = use_state(|| table_ref.borrow().state().clone());
314 let trigger = use_state(|| 0u32);
315
316 if *last_prop_data.borrow() != incoming_data {
318 {
320 let mut table = table_ref.borrow_mut();
321 table.set_data_indexed(incoming_data.clone());
322 table.process();
323 }
324
325 *last_prop_data.borrow_mut() = incoming_data;
327
328 *data_version.borrow_mut() += 1;
330 }
331
332 UseTableHandle {
333 table: table_ref,
334 state,
335 trigger,
336 data_version,
337 }
338}