Rendering your own types

As a text: DomDisplay

Numbers and strings can be put into dom! as they are. A type of your own, even if it implements Display, has to opt in with DomDisplay:

    use vertigo::{dom, DomDisplay, Value};

    #[derive(Clone, PartialEq)]
    struct Money {
        cents: u64,
    }

    impl std::fmt::Display for Money {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            write!(f, "${}.{:02}", self.cents / 100, self.cents % 100)
        }
    }

    // Allows to use Money in `dom!` as a text and as an attribute value
    impl DomDisplay for Money {}

    let price = Money { cents: 1999 };
    let balance = Value::new(Money { cents: 50000 });

    dom! {
        <div>
            <p title={&price}>"Price: " {&price}</p>
            <p>"Balance: " {balance}</p>
        </div>
    }

That one line covers the value and references to it, both as a text and as an attribute value. Value and Computed of a type implementing Display can be embedded as a text even without it.

If the type comes from another crate, you can't implement DomDisplay for it. Pass value.to_string() or wrap the value in a type of your own. Date and time types from chrono and Decimal from rust_decimal are already supported, when chrono or rust_decimal feature of vertigo is enabled.

As a DOM: EmbedDom

A type can also render itself into real DOM, by implementing EmbedDom:

    use vertigo::{css, dom, DomNode, EmbedDom};

    struct Badge {
        label: String,
        count: u32,
    }

    // Allows to put a Badge directly into `dom!`
    impl EmbedDom for Badge {
        fn embed(self) -> DomNode {
            let css = css! {"
                padding: 2px 6px;
                border-radius: 8px;
                background-color: #e07020;
            "};

            dom! {
                <span {css}>{self.label} " " {self.count}</span>
            }
        }
    }

    let inbox = Badge {
        label: "Inbox".to_string(),
        count: 3,
    };

    dom! {
        <nav>{inbox}</nav>
    }

A type can implement either DomDisplay or EmbedDom, not both.