|
Hello, I was wondering how to filter Virtual List that use a let list = use_signal(|| {
let mut u = Vec::<NotCloneableListElement>::new();
for i in 1..40000 {
u.push(NotCloneableListElement { name: format!("Test_{}", i).to_string()});
}
u
});with let list = use_store(|| {
let mut u = Vec::<NotCloneableListElement>::new();
for i in 1..40000 {
u.push(NotCloneableListElement { name: format!("Test_{}", i).to_string()});
}
u
});I managed to do it for a non-store list, although my approach is a bit messy. If anybody has a cleaner approach, I would love to see it. Thank you! :) use dioxus::prelude::*;
use crate::components::virtual_list::VirtualList;
const INLINE_STYLE: &str = r#".dx-virtual-list-container {
position: relative;
max-height: 36rem;
contain: layout paint;
overflow-y: auto;
}
.dx-virtual-list-demo {
display: flex;
flex-direction: column;
margin: 0 auto;
gap: 0.75rem;
}
.dx-virtual-list-card {
padding: 0.75rem 0.9rem;
border: 1px solid var(--primary-color-6);
border-radius: 0.625rem;
background: var(--primary-color-2);
}
.dx-virtual-list-card h3 {
margin: 0 0 0.3rem;
color: var(--primary-color-12);
font-size: 0.95rem;
}
.dx-virtual-list-card p {
margin: 0;
color: var(--primary-color-11);
font-size: 0.875rem;
line-height: 1.4;
}"#;
struct NotCloneableListElement {
name: String
}
/// The Home page component that will be rendered when the current route is `[Route::Home]`
#[component]
pub fn Show() -> Element {
let list = use_signal(|| {
let mut u = Vec::<NotCloneableListElement>::new();
for i in 1..40000 {
u.push(NotCloneableListElement { name: format!("Test_{}", i).to_string()});
}
u
});
let mut filter_word: Signal<String> = use_signal(|| "".to_string());
let filtered_list = use_memo(move || {
list.iter().enumerate().filter(|ele| (ele.1.name).to_lowercase().contains(&filter_word().to_lowercase().as_str())).map(|(x, _)| x).collect::<Vec<_>>()
});
rsx! {
div { class: "dx-virtual-list-demo",
input {
oninput: move |event| {
filter_word.set(event.value());
},
placeholder: "Filter Names",
name: "filter",
value: "{filter_word().to_uppercase()}",
}
div {
style { {INLINE_STYLE} }
VirtualList {
// Total number of items.
count: filtered_list.len(),
// Render buffer (approximate row count) above and below viewport.
buffer: 100usize,
// Row renderer callback receives the absolute index.
estimate_size: |_| 48,
render_item: move |idx: usize| {
let peek_idx = filtered_list.get(idx).expect("error1").cloned();
let lock_list = list.read();
let name = lock_list.get(peek_idx).expect("error2").name.as_str();
rsx! {
article { class: "dx-virtual-list-card", key: "{idx}", "{idx} {name}" }
}
},
}
}
}
}
} |
Replies: 1 comment 2 replies
|
With a Store, iter() and get() are the store's own methods and they hand you a child store per item instead of a reference to the item, which is why ele.1.name stops compiling. Store still implements Readable though, so if you call list.read() first you get a plain &Vec and your existing logic works unchanged: let filtered_list = use_memo(move || {
let f = filter_word().to_lowercase();
list.read().iter().enumerate().filter(|(_, e)| e.name.to_lowercase().contains(&f)).map(|(i, _)| i).collect::<Vec<_>>()
});Your render_item can stay exactly as it is, list.read() plus indexing works the same on a store as on a signal. Note I also lowercased the filter once outside the closure, your version did that for every one of the 40k items on each keystroke. Where the store actually pays off is the row. list.get(i) gives you a Store for just that element ( dioxus/packages/stores/src/impls/slice.rs Line 73 in 57d6794 One small thing, use the original index (peek_idx) as the key rather than idx, otherwise keys shift every time the filter changes. |
With a Store, iter() and get() are the store's own methods and they hand you a child store per item instead of a reference to the item, which is why ele.1.name stops compiling. Store still implements Readable though, so if you call list.read() first you get a plain &Vec and your existing logic works unchanged:
Your render_item can stay exactly as it is, list.read() plus indexing works the same on a store as on a signal. Note I also lowercased the filter once outside the closure, your …