diff --git a/crates/macro/src/html_tree/html_tag/mod.rs b/crates/macro/src/html_tree/html_tag/mod.rs
index e74f04dd417..f1e020813a3 100644
--- a/crates/macro/src/html_tree/html_tag/mod.rs
+++ b/crates/macro/src/html_tree/html_tag/mod.rs
@@ -137,7 +137,7 @@ impl ToTokens for HtmlTag {
#vtag.add_classes(vec![#(&(#classes)),*]);
},
ClassesForm::Single(classes) => quote! {
- #vtag.set_classes(&(#classes));
+ #vtag.set_classes(#classes);
},
});
diff --git a/src/services/resize.rs b/src/services/resize.rs
index 1af970ab962..c94d032cba6 100644
--- a/src/services/resize.rs
+++ b/src/services/resize.rs
@@ -1,8 +1,10 @@
//! This module contains the implementation of a service that listens for browser window resize events.
use stdweb::Value;
+use stdweb::{
+ js,
+ web::{window, Window},
+};
use yew::callback::Callback;
-use stdweb::{js, web::{window, Window}};
-
/// A service that fires events when the browser window resizes.
#[derive(Default)]
diff --git a/src/virtual_dom/mod.rs b/src/virtual_dom/mod.rs
index 69c1b49c77d..ce461f536fe 100644
--- a/src/virtual_dom/mod.rs
+++ b/src/virtual_dom/mod.rs
@@ -6,10 +6,10 @@ pub mod vnode;
pub mod vtag;
pub mod vtext;
+use indexmap::set::IndexSet;
use std::collections::HashMap;
use std::fmt;
use stdweb::web::{Element, EventListenerHandle, Node};
-use indexmap::set::IndexSet;
pub use self::vcomp::VComp;
pub use self::vlist::VList;
@@ -41,7 +41,62 @@ type Listeners = Vec>>;
type Attributes = HashMap;
/// A set of classes.
-type Classes = IndexSet;
+#[derive(Debug)]
+pub struct Classes {
+ set: IndexSet,
+}
+
+impl Classes {
+ /// Creates empty set of classes.
+ pub fn new() -> Self {
+ Self {
+ set: IndexSet::new(),
+ }
+ }
+
+ /// Adds a class to a set.
+ pub fn push(&mut self, class: &str) {
+ self.set.insert(class.into());
+ }
+
+ /// Check the set contains a class.
+ pub fn contains(&self, class: &str) -> bool {
+ self.set.contains(class)
+ }
+}
+
+impl ToString for Classes {
+ fn to_string(&self) -> String {
+ let mut buf = String::new();
+ for class in &self.set {
+ buf.push_str(class);
+ buf.push(' ');
+ }
+ buf.pop();
+ buf
+ }
+}
+
+impl From<&str> for Classes {
+ fn from(t: &str) -> Self {
+ let set = t.split_whitespace().map(String::from).collect();
+ Self { set }
+ }
+}
+
+impl From for Classes {
+ fn from(t: String) -> Self {
+ let set = t.split_whitespace().map(String::from).collect();
+ Self { set }
+ }
+}
+
+impl> From> for Classes {
+ fn from(t: Vec) -> Self {
+ let set = t.iter().map(|x| x.as_ref().to_string()).collect();
+ Self { set }
+ }
+}
/// Patch for DOM node modification.
enum Patch {
diff --git a/src/virtual_dom/vtag.rs b/src/virtual_dom/vtag.rs
index c78d9196aaa..021d359425e 100644
--- a/src/virtual_dom/vtag.rs
+++ b/src/virtual_dom/vtag.rs
@@ -96,7 +96,7 @@ impl VTag {
pub fn add_class(&mut self, class: &str) {
let class = class.trim();
if !class.is_empty() {
- self.classes.insert(class.into());
+ self.classes.push(class);
}
}
@@ -107,7 +107,7 @@ impl VTag {
for class in classes {
let class = class.trim();
if !class.is_empty() {
- self.classes.insert(class.into());
+ self.classes.push(class);
}
}
}
@@ -115,8 +115,8 @@ impl VTag {
/// Add classes to this virtual node. Actually it will set by
/// [Element.classList.add](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList)
/// call later.
- pub fn set_classes(&mut self, classes: &str) {
- self.classes = classes.split_whitespace().map(String::from).collect();
+ pub fn set_classes(&mut self, classes: impl Into) {
+ self.classes = classes.into();
}
/// Sets `value` for an
@@ -187,18 +187,21 @@ impl VTag {
// Only change what is necessary.
let to_add = self
.classes
- .difference(&ancestor.classes)
+ .set
+ .difference(&ancestor.classes.set)
.map(|class| Patch::Add(class.to_owned(), ()));
changes.extend(to_add);
let to_remove = ancestor
.classes
- .difference(&self.classes)
+ .set
+ .difference(&self.classes.set)
.map(|class| Patch::Remove(class.to_owned()));
changes.extend(to_remove);
} else {
// Add everything
let to_add = self
.classes
+ .set
.iter()
.map(|class| Patch::Add(class.to_owned(), ()));
changes.extend(to_add);
@@ -558,7 +561,7 @@ impl PartialEq for VTag {
return false;
}
- if self.classes.iter().ne(other.classes.iter()) {
+ if self.classes.set.iter().ne(other.classes.set.iter()) {
return false;
}
diff --git a/tests/vtag_test.rs b/tests/vtag_test.rs
index 211b11bad3f..8a55ea560c7 100644
--- a/tests/vtag_test.rs
+++ b/tests/vtag_test.rs
@@ -216,6 +216,24 @@ fn supports_multiple_classes_string() {
}
}
+#[test]
+fn supports_multiple_classes_vec() {
+ let mut classes = vec!["class-1"];
+ classes.push("class-2");
+ let a: VNode = html! {
+
+ };
+
+ if let VNode::VTag(vtag) = a {
+ println!("{:?}", vtag.classes);
+ assert!(vtag.classes.contains("class-1"));
+ assert!(vtag.classes.contains("class-2"));
+ assert!(!vtag.classes.contains("class-3"));
+ } else {
+ panic!("vtag expected");
+ }
+}
+
fn assert_vtag(node: &mut VNode) -> &mut VTag {
if let VNode::VTag(vtag) = node {
return vtag;
@@ -261,16 +279,9 @@ fn keeps_order_of_classes() {
};
- if let VNode::VTag(mut vtag) = a {
+ if let VNode::VTag(vtag) = a {
println!("{:?}", vtag.classes);
- assert_eq!(
- vtag.classes.drain(..).collect::>(),
- vec![
- String::from("class-1"),
- String::from("class-2"),
- String::from("class-3")
- ]
- )
+ assert_eq!(vtag.classes.to_string(), "class-1 class-2 class-3");
}
}