vertigo_forms/select/
select.rs1use std::ops::Not;
2
3use vertigo::{Computed, DomNode, Value, bind, computed_tuple, dom, render::render_list};
4
5pub struct Select<T: Clone + PartialEq + 'static> {
29 pub value: Value<T>,
30 pub options: Computed<Vec<T>>,
31}
32
33impl<T> Select<T>
34where
35 T: Clone + From<String> + PartialEq + ToString + 'static,
36{
37 pub fn into_component(self) -> Self {
38 self
39 }
40
41 pub fn mount(&self) -> DomNode {
42 let Self { value, options } = self;
43 let on_change = bind!(value, |new_value: String| {
44 value.set(new_value.into());
45 });
46
47 let empty = computed_tuple!(value, options).render_value_option(|(value, options)| {
48 options
49 .contains(&value)
50 .not()
51 .then(|| dom! { <option value="" selected="selected" /> })
52 });
53
54 let list = render_list(options, |item| item.to_string(), {
55 let value = value.clone();
56 move |item: &Computed<T>| {
57 let item = item.clone();
58 let text_item = item.map(|item| item.to_string());
59 let selected = computed_tuple!(item, value)
60 .map(|(item, value)| (item == value).then(|| "selected".to_string()));
61 dom! { <option value={&text_item} {selected}>{text_item}</option> }
62 }
63 });
64
65 dom! {
66 <select {on_change}>
67 {empty}
68 {list}
69 </select>
70 }
71 }
72}