toml
[dependencies]
view = "0.4"
Constructing view heirarchies in Rust is a bit tedious. This is a macro for constructing views in a non framework specific manner. It's more struct oriented compared to a technology like JSX and borrows in broad strokes some ideas from SwiftUI.
This example shows everything that's possible
rust
let images = vec!["coffee.png","cream.png","sugar.png"];
let show_coupon = false;
let v = view!{
VStack {
Image("company.png")
Button(text:"order".to_string(),style:BOLD)
.on_click(|| do_order()) {
Image("order_icon.png")
}
For(i in images.iter()) { Image(i) }
If(show_coupon) { Coupon }
Legal
}
};
Below is all the code this macro saves you from writing yourself.
```rust let images = vec!["coffee.png", "cream.png", "sugar.png"]; let show_legal = false;
let s = { let mut o = VStack { ..Default::default() }; o.addviewchild({ let mut o = Image::new("company.png"); o }); o.addviewchild({ let mut o = Button { text: "order".tostring(), style: BOLD, ..Default::default() }; o.onclick(|| doorder()); o.onclick(|| doorder()); o.addviewchild({ let mut o = Image::new("ordericon.png"); o }); o }); for i in images.iter() { o.addviewchild({ let mut o = Image::new(i); o }); } o.addviewchild({ let mut o = Footer { ..Default::default() }; o }); if showlegal { o.addview_child({ let mut o = Legal { ..Default::default() }; o }); } o }; ```
This project isn't framework specific, but it does have a few rules:
* views that have children must have a function add_view_child
implemented
* views must implement Default trait for property construction (e.g Button(text:"click me".to_string())
)
* views must have a 'new' constructor function for simple construction (e.g Button("click me")
)
Here's a basic example of implementing these rules, though they can be implemented in any way you choose with any trait you like.
```rust
trait View {}
struct VStack {
direction: u8,
children: Vec
impl VStack { fn new(direction:u8) -> Self { VStack{ direction:direction, children:vec![] } }
fn addviewchild<'a, T>(&'a mut self, child: Box
impl View for VStack {}
struct Button { text:String }
impl Button { fn new(text:String) -> Self { Button{text:text} } }
impl View for Button {} ```
```rust use view::*;
struct VNode {
vnode_type: &'static str,
children: Vec
impl VNode { fn addclass(&mut self, c: &str) { self.classes.push(c.tostring()) }
fn add_view_child(&mut self, child: VNode) {
self.children.push(child);
}
fn render_to_string(&self) -> String {
if let Some(t) = &self.text {
t.clone()
} else {
format!(
"<{} class=\"{}\">{}</{}>",
self.vnode_type,
self.classes.join(","),
self.children
.iter()
.map(|c| c.render_to_string())
.collect::<Vec<String>>()
.join(""),
self.vnode_type
)
}
}
}
type Div = VNode;
impl Default for Div { fn default() -> Self { VNode { vnode_type: "div", children: vec![], classes: vec![], text: None, } } }
type Text = VNode;
impl Text { fn new(t: &str) -> Self { VNode { vnodetype: "text", children: vec![], classes: vec![], text: Some(t.tostring()), } } }
fn main() { let html = view! { Div.addclass("greeting"){ Text("Hello World!") } }; println!("{}", html.renderto_string()); } ```
This project is licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in view by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.