In the code section below there is a button which adds another option to the select
, by using the let add_option
, which internally uses the signal selectionOptions.update
.
Once the button was pressed there is a 5th element, the 44l
and it appears and can be selected but the drop-down text is not updated.
The info!("n[0]: {} {}", n[0].label, n[0].amount)
in the add_option call is printed to the F12 console in the webbrowser with the 200 value though.
n[0]: h0rses 200
The print button also loggs the correct value:
h0rses 200
I'm probably not using the signals correctly but I don't know what is going wrong.
I have this code:
#[component]
pub fn DynSelector() -> impl IntoView {
// type SelectionHolder = Vec<(usize, (ReadSignal<i32>, WriteSignal<i32>))>;
// #[derive(Copy, Clone)]
// struct SelectionUpdater {
// set_selectionOptions: WriteSignal<SelectionHolder>,
// }
#[derive(Debug, Clone, Copy)]
pub struct SelectionOption {
pub label: &'static str,
pub id: u32,
pub amount: u32,
}
let selectionOptions1: Vec<SelectionOption> = vec![
SelectionOption{ label: "h0rses", id: 0, amount: 0},
SelectionOption{ label: "b1rds", id: 1, amount: 10},
SelectionOption{ label: "2nfish", id: 2, amount: 0},
SelectionOption{ label: "3lk", id: 3, amount: 20},
];
// let selectionOptions2: Vec<SelectionOption> = vec![
// SelectionOption{ label: "h0rses", id: 0, amount: 0},
// SelectionOption{ label: "b1rds", id: 1, amount: 10},
// SelectionOption{ label: "2nfish", id: 2, amount: 0},
// SelectionOption{ label: "3lk", id: 3, amount: 20},
// SelectionOption{ label: "4eel", id: 4, amount: 20},
// ];
let default_selection: RwSignal<Option<u32>> = create_rw_signal(Some(0));
let selectionOptions = create_rw_signal::<Vec<SelectionOption>>(selectionOptions1);
let print = move |_| {
let s = selectionOptions.get();
info!("{} {}", s[0].label, s[0].amount);
};
let add_option = move |_| {
let a = SelectionOption{ label: "4eel", id: 4, amount: 20};
selectionOptions.update(|n| {
n[0].amount = 200;
n.push(a);
info!("n[0]: {} {}", n[0].label, n[0].amount)
});
};
view! {
<div style="background:#eae3ff">
<select
id = "mymultiselect"
on:change = move |ev| {
let target_value = event_target_value(&ev);
if target_value.is_empty() {
default_selection.set(None);
} else {
match target_value.parse() {
Ok(v) => {
info!("you selected {}", v);
default_selection.set(Some(v))
},
Err(_) => {
error!("Error: Unexpected option value {target_value}");
},
}
}
}
>
<For
each = move || selectionOptions.get()
key = |option| option.id
let:option
>
<option
value = option.id
default_selection = (default_selection.get() == Some(option.id))
> {
let v = format!("{} - {}", option.label, option.amount);
v
}
</option>
</For>
</select>
<p>
"You selected: "
<span data-testid="mymultiselection">{move || {
let selected_option = default_selection.get();
match selected_option {
Some(v) => {
let l = selectionOptions.get()[v as usize].label;
let a = selectionOptions.get()[v as usize].amount;
format!("{} - {}", l, a.to_string())
},
None => "no idea...".to_string()
}
}
}</span>
<button on:click=add_option>
"Add another option to selector"
</button>
<button on:click=print>
"Print"
</button>
</p>
</div>
}
}
The solution was this: