description: Both HTML and SVG elements are supported

Elements

Tag Structure

Element tags must either self-close <... /> or have a corresponding close tag for each open tag

{% tabs %} {% tab title="Open - Close" %}


#![allow(unused_variables)]
fn main() {
html! {
  <div id="my_div"></div>
}
}

{% endtab %}

{% tab title="INVALID" %}


#![allow(unused_variables)]
fn main() {
html! {
  <div id="my_div"> // <- MISSING CLOSE TAG
}
}

{% endtab %}

{% tab title="Self-Closing" %}


#![allow(unused_variables)]
fn main() {
html! {
  <input id="my_input" />
}
}

{% endtab %}

{% tab title="INVALID" %}


#![allow(unused_variables)]
fn main() {
html! {
  <input id="my_input"> // <- MISSING SELF-CLOSE
}
}

{% endtab %} {% endtabs %}

{% hint style="info" %} For convenience, elements which usually require a closing tag are allowed to self-close. For example, writing html! { <div class="placeholder" /> } is valid. {% endhint %}

Children

Create complex nested HTML and SVG layouts with ease:

{% tabs %} {% tab title="HTML" %}


#![allow(unused_variables)]
fn main() {
html! {
    <div>
        <div data-key="abc"></div>
        <div class="parent">
            <span class="child" value="anything"></span>
            <label for="first-name">{ "First Name" }</label>
            <input type="text" id="first-name" value="placeholder" />
            <input type="checkbox" checked=true />
            <textarea value="write a story" />
            <select name="status">
                <option selected=true disabled=false value="">{ "Selected" }</option>
                <option selected=false disabled=true value="">{ "Unselected" }</option>
            </select>
        </div>
    </div>
}
}

{% endtab %}

{% tab title="SVG" %}


#![allow(unused_variables)]
fn main() {
html! {
    <svg width="149" height="147" viewBox="0 0 149 147" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M60.5776 13.8268L51.8673 42.6431L77.7475 37.331L60.5776 13.8268Z" fill="#DEB819"/>
        <path d="M108.361 94.9937L138.708 90.686L115.342 69.8642" stroke="black" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
        <g filter="url(#filter0_d)">
            <circle cx="75.3326" cy="73.4918" r="55" fill="#FDD630"/>
            <circle cx="75.3326" cy="73.4918" r="52.5" stroke="black" stroke-width="5"/>
        </g>
        <circle cx="71" cy="99" r="5" fill="white" fill-opacity="0.75" stroke="black" stroke-width="3"/>
        <defs>
            <filter id="filter0_d" x="16.3326" y="18.4918" width="118" height="118" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
                <feGaussianBlur stdDeviation="2"/>
                <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
            </filter>
        </defs>
    </svg>
}
}

{% endtab %} {% endtabs %}

Classes

There are a number of convenient options for specifying classes for an element:

{% tabs %} {% tab title="Literal" %}


#![allow(unused_variables)]
fn main() {
html! {
  <div class="container"></div>
}
}

{% endtab %}

{% tab title="Multiple" %}


#![allow(unused_variables)]
fn main() {
html! {
  <div class="container center-align"></div>
}
}

{% endtab %}

{% tab title="Interpolated" %}


#![allow(unused_variables)]
fn main() {
html! {
  <div class=format!("{}-container", size)></div>
}
}

{% endtab %}

{% tab title="Expression" %}


#![allow(unused_variables)]
fn main() {
html! {
  <div class=self.classes()></div>
}
}

{% endtab %}

{% tab title="Tuple" %}


#![allow(unused_variables)]
fn main() {
html! {
  <div class=("class-1", "class-2")></div>
}
}

{% endtab %}

{% tab title="Vector" %}


#![allow(unused_variables)]
fn main() {
html! {
  <div class=vec!["class-1", "class-2"]></div>
}
}

{% endtab %} {% endtabs %}

Listeners

Listener attributes need to be passed a Callback which is a wrapper around a closure. How you create your callback depends on how you wish your app to react to a listener event:

{% tabs %} {% tab title="Component Handler" %}


#![allow(unused_variables)]
fn main() {
struct MyComponent {
    link: ComponentLink<Self>,
}

enum Msg {
    Click,
}

impl Component for MyComponent {
    type Message = Msg;
    type Properties = ();

    fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
        MyComponent { link }
    }

    fn update(&mut self, msg: Self::Message) -> ShouldRender {
        match msg {
            Msg::Click => {
                // Handle Click
            }
        }
    }

    fn view(&self) -> Html {
        // Create a callback from a component link to handle it in a component
        let click_callback = self.link.callback(|_: ClickEvent| Msg::Click);
        html! {
            <button onclick=click_callback>
                { "Click me!" }
            </button>
        }
    }
}
}

{% endtab %}

{% tab title="Agent Handler" %}


#![allow(unused_variables)]
fn main() {
struct MyComponent {
    worker: Dispatcher<MyWorker>,
}

impl Component for MyComponent {
    type Message = ();
    type Properties = ();

    fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
        MyComponent {
            worker: MyWorker::dispatcher()
        }
    }

    fn update(&mut self, _: Self::Message) -> ShouldRender {
        false
    }

    fn view(&self) -> Html {
        // Create a callback from a worker to handle it in another context
        let click_callback = self.worker.callback(|_: ClickEvent| WorkerMsg::Process);
        html! {
            <button onclick=click_callback>
                { "Click me!" }
            </button>
        }
    }
}
}

{% endtab %}

{% tab title="Other Cases" %}


#![allow(unused_variables)]
fn main() {
struct MyComponent;

impl Component for MyComponent {
    type Message = ();
    type Properties = ();

    fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
        MyComponent
    }

    fn update(&mut self, _: Self::Message) -> ShouldRender {
        false
    }

    fn view(&self) -> Html {
        // Create an ephemeral callback
        let click_callback = Callback::from(|| {
            ConsoleService::new().log("clicked!");
        });

        html! {
            <button onclick=click_callback>
                { "Click me!" }
            </button>
        }
    }
}
}

{% endtab %} {% endtabs %}