Skip to content

el_key - alpha version #356

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

[unreleased]
- [BREAKING] Changed `perform_cmd` and `fetch` return type to `T` instead of `Result<T, T>`.
- Added `el_key` method for adding keys to `El`s [WIP].

## v0.6.0
- Implemented `UpdateEl` for `Filter` and `FilterMap`.
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ pub mod prelude {
// https://github.com/rust-lang-nursery/reference/blob/master/src/macros-by-example.md
shortcuts::*,
virtual_dom::{
el_ref::el_ref, AsAtValue, At, AtValue, CSSValue, El, ElRef, Ev, EventHandler, Node,
St, Tag, UpdateEl, View,
el_key, el_ref::el_ref, AsAtValue, At, AtValue, CSSValue, El, ElRef, Ev, EventHandler,
Node, St, Tag, UpdateEl, View,
},
};
pub use indexmap::IndexMap; // for attrs and style to work.
Expand Down
2 changes: 1 addition & 1 deletion src/virtual_dom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub use attrs::Attrs;
pub use el_ref::{el_ref, ElRef, SharedNodeWs};
pub use event_handler_manager::{EventHandler, EventHandlerManager, Listener};
pub use mailbox::Mailbox;
pub use node::{El, IntoNodes, Node, Text};
pub use node::{el_key, El, ElKey, IntoNodes, Node, Text};
pub use style::Style;
pub use update_el::UpdateEl;
pub use values::{AsAtValue, AtValue, CSSValue};
Expand Down
2 changes: 1 addition & 1 deletion src/virtual_dom/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub mod el;
pub mod into_nodes;
pub mod text;

pub use el::El;
pub use el::{el_key, El, ElKey};
pub use into_nodes::IntoNodes;
pub use text::Text;

Expand Down
24 changes: 24 additions & 0 deletions src/virtual_dom/node/el.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@ use crate::browser::{
};
use std::borrow::Cow;

// ------ ElKey ------

#[allow(clippy::module_name_repetitions)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ElKey(String);

#[allow(clippy::module_name_repetitions)]
/// Attach given `key` to the `El`.
///
/// ## Warning
///
/// WIP
/// - it doesn't patch elements with the different keys, BUT it replace the old element with the new one.
/// - `key` restriction (have to implements `ToString`) will be probably relaxed in the future.
pub fn el_key(key: &impl ToString) -> ElKey {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be Display instead? Citing docs:

This trait is automatically implemented for any type which implements the Display trait. As such, ToString shouldn't be implemented directly: Display should be implemented instead, and you get the ToString implementation for free.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I know this advice. I don't implement ToString, I'm just using impl instead of generics here.
I think - if I understand that advice correctly - that ToString is basically something like a subset of Display. So I chose to write &impl ToString because it sounds to me a little bit more relaxed than Display. And I don't want to "display" the key anywhere, I just want to convert it to String so it feels also more descriptive to me.

ElKey(key.to_string())
}

// ------ El ------

/// A component in our virtual DOM.
///
/// _Note:_ `Listener`s in `El`'s `event_handler_manager` are not cloned, but recreated during VDOM patching.
Expand All @@ -29,6 +49,7 @@ pub struct El<Ms: 'static> {
/// The actual DOM element/node.
pub node_ws: Option<web_sys::Node>,
pub refs: Vec<SharedNodeWs>,
pub key: Option<ElKey>,
}

// @TODO remove custom impl once https://github.com/rust-lang/rust/issues/26925 is fixed
Expand All @@ -43,6 +64,7 @@ impl<Ms> Clone for El<Ms> {
namespace: self.namespace.clone(),
node_ws: self.node_ws.clone(),
refs: self.refs.clone(),
key: self.key.clone(),
}
}
}
Expand Down Expand Up @@ -71,6 +93,7 @@ impl<Ms: 'static, OtherMs: 'static> MessageMapper<Ms, OtherMs> for El<Ms> {
namespace: self.namespace,
event_handler_manager: self.event_handler_manager.map_msg(f),
refs: self.refs,
key: self.key,
}
}
}
Expand All @@ -94,6 +117,7 @@ impl<Ms> El<Ms> {
namespace: None,
node_ws: None,
refs: Vec::new(),
key: None,
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/virtual_dom/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ fn patch_el<'a, Ms, Mdl, ElC: View<Ms>, GMs>(
// Namespaces can't be patched, since they involve create_element_ns instead of create_element.
// Custom elements can't be patched, because we need to reinit them (Issue #325). (@TODO is there a better way?)
// Something about this element itself is different: patch it.
if old.tag != new.tag || old.namespace != new.namespace || old.is_custom() {
if old.tag != new.tag || old.namespace != new.namespace || old.is_custom() || old.key != new.key
{
let old_el_ws = old.node_ws.as_ref().expect("Missing websys el");

// We don't use assign_nodes directly here, since we only have access to
Expand Down
8 changes: 7 additions & 1 deletion src/virtual_dom/update_el.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Attrs, El, ElRef, EventHandler, Node, Style, Tag, Text};
use super::{Attrs, El, ElKey, ElRef, EventHandler, Node, Style, Tag, Text};

/// `UpdateEl` is used to distinguish arguments in element-creation macros, and handle
/// each type appropriately.
Expand Down Expand Up @@ -133,6 +133,12 @@ impl<Ms, E: Clone> UpdateEl<El<Ms>> for ElRef<E> {
}
}

impl<Ms> UpdateEl<El<Ms>> for ElKey {
fn update(self, el: &mut El<Ms>) {
el.key = Some(self);
}
}

// ----- Iterators ------

impl<Ms, I, U, F> UpdateEl<El<Ms>> for std::iter::Map<I, F>
Expand Down