Skip to content

Commit

Permalink
fix: correctly reset classes when using Option<T> (#3164)
Browse files Browse the repository at this point in the history
  • Loading branch information
gbj authored Oct 25, 2024
1 parent 76facf9 commit af61be0
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 50 deletions.
52 changes: 42 additions & 10 deletions tachys/src/html/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ pub trait IntoClass: Send {

/// “Resolves” this into a type that is not waiting for any asynchronous data.
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;

/// Reset the class list to the state before this class was added.
fn reset(state: &mut Self::State);
}

impl<T: IntoClass> IntoClass for Option<T> {
Expand Down Expand Up @@ -218,15 +221,15 @@ impl<T: IntoClass> IntoClass for Option<T> {
fn rebuild(self, state: &mut Self::State) {
let el = &state.0;
let prev_state = &mut state.1;
let maybe_next_t_state = match (prev_state, self) {
(Some(_prev_t_state), None) => {
Rndr::remove_attribute(el, "class");
let maybe_next_t_state = match (prev_state.take(), self) {
(Some(mut prev_t_state), None) => {
T::reset(&mut prev_t_state);
Some(None)
}
(None, Some(t)) => Some(Some(t.build(el))),
(Some(prev_t_state), Some(t)) => {
t.rebuild(prev_t_state);
None
(Some(mut prev_t_state), Some(t)) => {
t.rebuild(&mut prev_t_state);
Some(Some(prev_t_state))
}
(None, None) => Some(None),
};
Expand Down Expand Up @@ -256,6 +259,12 @@ impl<T: IntoClass> IntoClass for Option<T> {
None
}
}

fn reset(state: &mut Self::State) {
if let Some(prev_t_state) = &mut state.1 {
T::reset(prev_t_state);
}
}
}

impl<'a> IntoClass for &'a str {
Expand Down Expand Up @@ -308,6 +317,11 @@ impl<'a> IntoClass for &'a str {
async fn resolve(self) -> Self::AsyncOutput {
self
}

fn reset(state: &mut Self::State) {
let (el, _prev) = state;
Rndr::remove_attribute(el, "class");
}
}

impl IntoClass for String {
Expand Down Expand Up @@ -360,6 +374,11 @@ impl IntoClass for String {
async fn resolve(self) -> Self::AsyncOutput {
self
}

fn reset(state: &mut Self::State) {
let (el, _prev) = state;
Rndr::remove_attribute(el, "class");
}
}

impl IntoClass for Arc<str> {
Expand Down Expand Up @@ -412,11 +431,16 @@ impl IntoClass for Arc<str> {
async fn resolve(self) -> Self::AsyncOutput {
self
}

fn reset(state: &mut Self::State) {
let (el, _prev) = state;
Rndr::remove_attribute(el, "class");
}
}

impl IntoClass for (&'static str, bool) {
type AsyncOutput = Self;
type State = (crate::renderer::types::ClassList, bool);
type State = (crate::renderer::types::ClassList, bool, &'static str);
type Cloneable = Self;
type CloneableOwned = Self;

Expand All @@ -440,7 +464,7 @@ impl IntoClass for (&'static str, bool) {
if !FROM_SERVER && include {
Rndr::add_class(&class_list, name);
}
(class_list, self.1)
(class_list, self.1, name)
}

fn build(self, el: &crate::renderer::types::Element) -> Self::State {
Expand All @@ -449,12 +473,12 @@ impl IntoClass for (&'static str, bool) {
if include {
Rndr::add_class(&class_list, name);
}
(class_list, self.1)
(class_list, self.1, name)
}

fn rebuild(self, state: &mut Self::State) {
let (name, include) = self;
let (class_list, prev_include) = state;
let (class_list, prev_include, prev_name) = state;
if include != *prev_include {
if include {
Rndr::add_class(class_list, name);
Expand All @@ -463,6 +487,7 @@ impl IntoClass for (&'static str, bool) {
}
}
*prev_include = include;
*prev_name = name;
}

fn into_cloneable(self) -> Self::Cloneable {
Expand All @@ -478,6 +503,11 @@ impl IntoClass for (&'static str, bool) {
async fn resolve(self) -> Self::AsyncOutput {
self
}

fn reset(state: &mut Self::State) {
let (class_list, _, name) = state;
Rndr::remove_class(class_list, name);
}
}

#[cfg(feature = "nightly")]
Expand Down Expand Up @@ -526,6 +556,8 @@ impl<const V: &'static str> IntoClass for crate::view::static_types::Static<V> {
async fn resolve(self) -> Self::AsyncOutput {
self
}

fn reset(_state: &mut Self::State) {}
}

/* #[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion tachys/src/html/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl<T: IntoStyle> IntoStyle for Option<T> {
(None, Some(t)) => Some(Some(t.build(el))),
(Some(mut prev_t_state), Some(t)) => {
t.rebuild(&mut prev_t_state);
None
Some(Some(prev_t_state))
}
(None, None) => Some(None),
};
Expand Down
5 changes: 5 additions & 0 deletions tachys/src/oco.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ impl IntoClass for Oco<'static, str> {
async fn resolve(self) -> Self::AsyncOutput {
self
}

fn reset(state: &mut Self::State) {
let (el, _prev) = state;
Rndr::remove_attribute(el, "class");
}
}

impl IntoStyle for Oco<'static, str> {
Expand Down
Loading

0 comments on commit af61be0

Please sign in to comment.