dioxus_element_plug/components/
pagination.rs1use dioxus::prelude::*;
2
3#[derive(Props, Clone, PartialEq)]
5pub struct PaginationProps {
6 #[props(default = 0)]
8 pub total: u32,
9
10 #[props(default = 1)]
12 pub current_page: u32,
13
14 #[props(default = 10)]
16 pub page_size: u32,
17
18 #[props(default = 7)]
20 pub pager_count: u32,
21
22 #[props(default = false)]
24 pub show_total: bool,
25
26 #[props(default = false)]
28 pub show_size_picker: bool,
29
30 #[props(default = false)]
32 pub show_jumper: bool,
33
34 #[props(default = "prev, pager, next".to_string())]
36 pub layout: String,
37
38 #[props(default = false)]
40 pub disabled: bool,
41
42 #[props(default = false)]
44 pub small: bool,
45
46 #[props(default)]
48 pub page_sizes: Vec<u32>,
49
50 #[props(default)]
52 pub on_current_change: Option<EventHandler<u32>>,
53
54 #[props(default)]
56 pub on_size_change: Option<EventHandler<u32>>,
57
58 #[props(default)]
59 pub class: Option<String>,
60
61 #[props(default)]
62 pub style: Option<String>,
63}
64
65#[component]
67pub fn Pagination(props: PaginationProps) -> Element {
68 let mut class_names = vec!["el-pagination".to_string()];
69 if props.small { class_names.push("el-pagination--small".to_string()); }
70 if props.disabled { class_names.push("is-disabled".to_string()); }
71 if let Some(ref c) = props.class { class_names.push(c.clone()); }
72
73 let total_pages = if props.page_size > 0 {
74 (props.total + props.page_size - 1) / props.page_size
75 } else {
76 1
77 };
78 let total_pages = total_pages.max(1);
79
80 rsx! {
81 div {
82 class: "{class_names.join(\" \")}",
83 style: props.style.clone().unwrap_or_default(),
84 role: "pagination",
85
86 if props.show_total {
87 span {
88 class: "el-pagination__total",
89 "Total {props.total}"
90 }
91 }
92
93 button {
95 class: "btn-prev el-pagination__button",
96 disabled: props.disabled || props.current_page <= 1,
97 onclick: move |_| {
98 if !props.disabled && props.current_page > 1 {
99 if let Some(handler) = props.on_current_change {
100 handler.call(props.current_page - 1);
101 }
102 }
103 },
104 "‹"
105 }
106
107 span {
109 class: "el-pager",
110 for page in 1..=total_pages.min(props.pager_count) {
111 button {
112 class: {
113 let mut cls = "el-pager__number".to_string();
114 if page == props.current_page { cls.push_str(" is-active"); }
115 cls
116 },
117 onclick: move |_| {
118 if !props.disabled {
119 if let Some(handler) = props.on_current_change {
120 handler.call(page);
121 }
122 }
123 },
124 "{page}"
125 }
126 }
127 if total_pages > props.pager_count {
128 span { class: "el-icon-more", "..." }
129 }
130 }
131
132 button {
134 class: "btn-next el-pagination__button",
135 disabled: props.disabled || props.current_page >= total_pages,
136 onclick: move |_| {
137 if !props.disabled && props.current_page < total_pages {
138 if let Some(handler) = props.on_current_change {
139 handler.call(props.current_page + 1);
140 }
141 }
142 },
143 "›"
144 }
145
146 if props.show_jumper {
147 span {
148 class: "el-pagination__jump",
149 "Go to"
150 input {
151 r#type: "number",
152 class: "el-pagination__editor",
153 value: "{props.current_page}",
154 disabled: props.disabled,
155 }
156 "pages"
157 }
158 }
159 }
160 }
161}