SignalSet now supports a trait for adding types that may be set via SignalSetWith.

This commit is contained in:
2024-03-05 14:41:32 +00:00
parent 7c1ab7ee0c
commit d020122ba1
5 changed files with 27 additions and 40 deletions

View File

@@ -97,6 +97,22 @@ pub trait SignalWith {
F: for<'a> FnOnce(Self::Value<'a>) -> O;
}
/// Types which may be set by [`SignalSet`]
pub trait SignalSetWith<T>: Sized {
fn set(&mut self, new_value: T);
}
impl<T> SignalSetWith<T> for T {
fn set(&mut self, new_value: T) {
*self = new_value;
}
}
impl<T> SignalSetWith<T> for Option<T> {
fn set(&mut self, new_value: T) {
*self = Some(new_value);
}
}
/// Signal set
pub trait SignalSet<Value> {
/// Sets the signal value
@@ -105,10 +121,11 @@ pub trait SignalSet<Value> {
impl<S, T> SignalSet<T> for S
where
S: SignalUpdate<Value = T>,
S: SignalUpdate,
S::Value: SignalSetWith<T>,
{
fn set(&self, new_value: T) {
self.update(|value| *value = new_value);
self.update(|value| SignalSetWith::set(value, new_value));
}
}

View File

@@ -1,7 +1,7 @@
//! `Option<T>` Signal with default value
// Imports
use crate::{SignalReplace, SignalSet, SignalUpdate, SignalWith};
use crate::{SignalReplace, SignalUpdate, SignalWith};
/// Wrapper for a `Signal<Option<T>>` with a default value
#[derive(Clone, Debug)]
@@ -38,15 +38,6 @@ where
}
}
impl<S, T> SignalSet<Option<T>> for WithDefault<S, T>
where
S: SignalSet<Option<T>>,
{
fn set(&self, new_value: Option<T>) {
self.inner.set(new_value)
}
}
impl<S, T> SignalReplace<T> for WithDefault<S, T>
where
S: SignalReplace<Option<T>>,

View File

@@ -6,6 +6,7 @@ use {
dynatos_html::{html, ElementWithAttr},
dynatos_reactive::SignalSet,
dynatos_util::{ev, EventTargetWithListener},
url::Url,
web_sys::Element,
};
@@ -21,8 +22,11 @@ where
.with_event_listener::<ev::Click>(move |ev| {
ev.prevent_default();
dynatos_context::with_expect::<Location, _, _>(|location| {
let new_location = new_location.as_ref();
location.set(new_location);
let new_location = &new_location.as_ref();
match new_location.parse::<Url>() {
Ok(new_location) => location.set(new_location),
Err(err) => tracing::warn!("Unable to parse new location as a valid url {new_location:?}: {err}"),
}
});
})
}

View File

@@ -2,7 +2,7 @@
// Imports
use {
dynatos_reactive::{Signal, SignalSet, SignalUpdate, SignalWith},
dynatos_reactive::{Signal, SignalUpdate, SignalWith},
dynatos_util::{ev, EventTargetAddListener},
url::Url,
wasm_bindgen::JsValue,
@@ -54,22 +54,6 @@ impl SignalWith for Location {
}
}
impl SignalSet<&'_ str> for Location {
fn set(&self, new_location: &'_ str) {
let window = web_sys::window().expect("Unable to get window");
let history = window.history().expect("Unable to get history");
// Push the new location into history
history
.push_state_with_url(&JsValue::UNDEFINED, "", Some(new_location))
.expect("Unable to push history");
// Then parse the location back
let new_location = self::parse_location_url();
self.0.update(|inner| inner.location = new_location);
}
}
impl SignalUpdate for Location {
type Value = Url;

View File

@@ -73,15 +73,6 @@ impl<T: 'static> SignalWith for QuerySignal<T> {
}
}
impl<T> SignalSet<T> for QuerySignal<T>
where
T: ToString + 'static,
{
fn set(&self, new_value: T) {
self.update(|value| *value = Some(new_value));
}
}
impl<T> SignalReplace<Option<T>> for QuerySignal<T>
where
T: ToString + 'static,