I'm struggling with complex onclick.
My Model has a function:
...
let on_click = |editing : EditSensor| -> Msg {
if !editing.is_valid() {
Msg::Nothing
}
else {
let sensor = Sensor {
id: editing.id,
latitude: editing.latitude.unwrap(),
longitude: editing.longitude.unwrap()
};
Msg::AddSensor(sensor)
}
};
let editing = self.editing_sensor.clone();
html! {
<form>
<fieldset class="uk-fieldset",>
<legend class="uk-legend",>{"Sensor"}</legend>
<input class={form_input_state(self.editing_sensor.has_valid_id())}, placeholder="Sensor ID", value=&self.editing_sensor.id, oninput=|e| Msg::EditingSensorId(e.value), />
<input class={form_input_state(self.editing_sensor.has_valid_latitude())}, placeholder="Latitude", value=latitude, oninput=|e|Msg::EditingSensorLatitude(e.value.parse::<f64>().ok()), />
<input class={form_input_state(self.editing_sensor.has_valid_longitude())}, placeholder="Longitude", value=longitude, oninput=|e| Msg::EditingSensorLongitude(e.value.parse::<f64>().ok()), />
<button class="uk-button uk-button-default",
disabled={!self.editing_sensor.is_valid()},
onclick= |_| {
on_click(editing)
},>
{"Add Sensor"}
</button>
</fieldset>
</form>
}
I cannot get on_click to work (lifetime issues). All of the examples have onclick simply returning a Msg but I want to do some validation and construct a Msg.
The typical way to accomplish this is to create a new Msg variant and in update, put the logic you currently have defined in your on_click closure for that variant. Call self.update(Msg::AddSensor) at end of your variants logic instead of returning it (also return false for ShouldRender..
in your onclick, return that message.
An abbreviated version of your example might look like;
/// update
match msg {
Msg::NewVariant => {
let editing = self.editing_sensor.clone(); // cloning may not be necessary here
if !editing.is_valid() {
self.update(Msg::Nothing) // Technically, you probably shouldn't redirect to a no-op message, instead, just do nothing.
}
else {
let sensor = Sensor {
id: editing.id,
latitude: editing.latitude.unwrap(),
longitude: editing.longitude.unwrap()
};
self.update(Msg::AddSensor(sensor))
}
return false;
}
Msg::AddSensor(sensor) => {},
Msg::Nothing => {}
}
/// view
html! {
<button onclick=|_| Msg::NewVariant, > {"Add Sensor"} </button>
}
Ultimately, Yew forces you to move as much of your logic that is dependent on your component's state into the update method. Keep your callbacks simple will make your life easier.
Question was answered
Most helpful comment
The typical way to accomplish this is to create a new
Msgvariant and in update, put the logic you currently have defined in your on_click closure for that variant. Call self.update(Msg::AddSensor) at end of your variants logic instead of returning it (also return false for ShouldRender..in your onclick, return that message.
An abbreviated version of your example might look like;
Ultimately, Yew forces you to move as much of your logic that is dependent on your component's state into the update method. Keep your callbacks simple will make your life easier.