Elements

DOM nodes

There are many reasons why you might want to create or manage DOM nodes manually in Yew, such as when integrating with JS libraries that can cause conflicts with managed components.

Using web-sys, you can create DOM elements and convert them into a Node - which can then be used as a Html value using VRef:

  1. use web_sys::{Element, Node};
  2. use yew::{Component, Context, html, Html};
  3. use gloo_utils::document;
  4. struct Comp;
  5. impl Component for Comp {
  6. type Message = ();
  7. type Properties = ();
  8. fn create(_ctx: &Context<Self>) -> Self {
  9. Self
  10. }
  11. fn view(&self, _ctx: &Context<Self>) -> Html {
  12. // Create a div element from the document
  13. let div: Element = document().create_element("div").unwrap();
  14. // Add content, classes etc.
  15. div.set_inner_html("Hello, World!");
  16. // Convert Element into a Node
  17. let node: Node = div.into();
  18. // Return that Node as a Html value
  19. Html::VRef(node)
  20. }
  21. }

Dynamic tag names

When building a higher-order component you might find yourself in a situation where the element’s tag name isn’t static. For example, you might have a Title component which can render anything from h1 to h6 depending on a level prop. Instead of having to use a big match expression, Yew allows you to set the tag name dynamically using @{name} where name can be any expression that returns a string.

  1. use yew::html;
  2. let level = 5;
  3. let text = "Hello World!".to_owned();
  4. html! {
  5. <@{format!("h{}", level)} class="title">{ text }</@>
  6. };

Boolean Attributes

Some content attributes (e.g checked, hidden, required) are called boolean attributes. In Yew, boolean attributes need to be set to a bool value:

  1. use yew::html;
  2. html! {
  3. <div hidden=true>
  4. { "This div is hidden." }
  5. </div>
  6. };

This will result in HTML that’s functionally equivalent to this:

  1. <div hidden>This div is hidden.</div>

Setting a boolean attribute to false is equivalent to not using the attribute at all; values from boolean expressions can be used:

  1. use yew::html;
  2. let no = 1 + 1 != 2;
  3. html! {
  4. <div hidden={no}>
  5. { "This div is NOT hidden." }
  6. </div>
  7. };

This will result in the following HTML:

  1. <div>This div is NOT hidden.</div>

String-like attributes

But apart from a select few boolean attributes, you will probably be dealing with a lot of string-like HTML attributes and Yew has a few option for those

  1. use yew::{html, virtual_dom::AttrValue};
  2. let str_placeholder = "I'm a str!";
  3. let string_placeholder = String::from("I'm a String!");
  4. let attrvalue_placeholder = AttrValue::from("I'm an AttrValue!");
  5. html! {
  6. <div>
  7. <input placeholder={str_placeholder} />
  8. <input placeholder={string_placeholder} />
  9. <input placeholder={attrvalue_placeholder} />
  10. </div>
  11. };

They are all valid but we encourage you to favor Yew’s custom AttrValue, especially if you need to clone or pass them as properties to another component.

Optional attributes for HTML elements

Most HTML attributes can use optional values (Some(x) or None). This allows us to omit the attribute if the attribute is marked as optional.

  1. use yew::html;
  2. let maybe_id = Some("foobar");
  3. html! {
  4. <div id={maybe_id}></div>
  5. };

If the attribute is set to None, the attribute won’t be set in the DOM.

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:

  • Component handler
  • Agent Handler
  • Other Cases
  1. use yew::{Component, Context, html, Html};
  2. struct MyComponent;
  3. enum Msg {
  4. Click,
  5. }
  6. impl Component for MyComponent {
  7. type Message = Msg;
  8. type Properties = ();
  9. fn create(_ctx: &Context<Self>) -> Self {
  10. Self
  11. }
  12. fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
  13. match msg {
  14. Msg::Click => {
  15. // Handle Click
  16. }
  17. };
  18. true
  19. }
  20. fn view(&self, ctx: &Context<Self>) -> Html {
  21. // Create a callback from a component link to handle it in a component
  22. let click_callback = ctx.link().callback(|_| Msg::Click);
  23. html! {
  24. <button onclick={click_callback}>
  25. { "Click me!" }
  26. </button>
  27. }
  28. }
  29. }
  1. use yew::{html, Component, Context, Html};
  2. use yew_agent::{Dispatcher, Dispatched};
  3. use website_test::agents::{MyWorker, WorkerMsg};
  4. struct MyComponent {
  5. worker: Dispatcher<MyWorker>,
  6. }
  7. impl Component for MyComponent {
  8. type Message = WorkerMsg;
  9. type Properties = ();
  10. fn create(_ctx: &Context<Self>) -> Self {
  11. MyComponent {
  12. worker: MyWorker::dispatcher(),
  13. }
  14. }
  15. fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
  16. self.worker.send(msg);
  17. false
  18. }
  19. fn view(&self, ctx: &Context<Self>) -> Html {
  20. // Create a callback from a worker to handle it in another context
  21. let click_callback = ctx.link().callback(|_| WorkerMsg::Process);
  22. html! {
  23. <button onclick={click_callback}>
  24. { "Click me!" }
  25. </button>
  26. }
  27. }
  28. }
  1. use yew::{Callback, Context, Component, html, Html};
  2. use weblog::console_log;
  3. struct MyComponent;
  4. impl Component for MyComponent {
  5. type Message = ();
  6. type Properties = ();
  7. fn create(_ctx: &Context<Self>) -> Self {
  8. MyComponent
  9. }
  10. fn view(&self, _ctx: &Context<Self>) -> Html {
  11. // Create an ephemeral callback
  12. let click_callback = Callback::from(|_| {
  13. console_log!("clicked!");
  14. });
  15. html! {
  16. <button onclick={click_callback}>
  17. { "Click me!" }
  18. </button>
  19. }
  20. }
  21. }

Relevant examples