diff --git a/tachys/src/html/mod.rs b/tachys/src/html/mod.rs
index c4225be702..67af1a5bd3 100644
--- a/tachys/src/html/mod.rs
+++ b/tachys/src/html/mod.rs
@@ -2,8 +2,11 @@ use self::attribute::Attribute;
use crate::{
hydration::Cursor,
no_attrs,
- prelude::AddAnyAttr,
- renderer::{CastFrom, Rndr},
+ prelude::{AddAnyAttr, Mountable},
+ renderer::{
+ dom::{Element, Node},
+ CastFrom, Rndr,
+ },
view::{Position, PositionState, Render, RenderHtml},
};
use std::borrow::Cow;
@@ -90,14 +93,41 @@ impl InertElement {
}
}
+/// Retained view state for [`InertElement`].
+pub struct InertElementState(Cow<'static, str>, Element);
+
+impl Mountable for InertElementState {
+ fn unmount(&mut self) {
+ self.1.unmount();
+ }
+
+ fn mount(&mut self, parent: &Element, marker: Option<&Node>) {
+ self.1.mount(parent, marker)
+ }
+
+ fn insert_before_this(&self, child: &mut dyn Mountable) -> bool {
+ self.1.insert_before_this(child)
+ }
+}
+
impl Render for InertElement {
- type State = crate::renderer::types::Element;
+ type State = InertElementState;
fn build(self) -> Self::State {
- Rndr::create_element_from_html(&self.html)
+ let el = Rndr::create_element_from_html(&self.html);
+ InertElementState(self.html, el)
}
- fn rebuild(self, _state: &mut Self::State) {}
+ fn rebuild(self, state: &mut Self::State) {
+ let InertElementState(prev, el) = state;
+ if &self.html != prev {
+ let mut new_el = Rndr::create_element_from_html(&self.html);
+ el.insert_before_this(&mut new_el);
+ el.unmount();
+ *el = new_el;
+ *prev = self.html;
+ }
+ }
}
impl AddAnyAttr for InertElement {
@@ -157,6 +187,6 @@ impl RenderHtml for InertElement {
let el = crate::renderer::types::Element::cast_from(cursor.current())
.unwrap();
position.set(Position::NextChild);
- el
+ InertElementState(self.html, el)
}
}
diff --git a/tachys/src/renderer/dom.rs b/tachys/src/renderer/dom.rs
index 11addfc7d5..bcac94fe52 100644
--- a/tachys/src/renderer/dom.rs
+++ b/tachys/src/renderer/dom.rs
@@ -444,7 +444,8 @@ impl Dom {
// TODO can be optimized to cache HTML strings or cache ?
let tpl = document().create_element("template").unwrap();
tpl.set_inner_html(html);
- Self::clone_template(tpl.unchecked_ref())
+ let tpl = Self::clone_template(tpl.unchecked_ref());
+ tpl.first_element_child().unwrap_or(tpl)
}
}