# Passing children and attributes
Often times, you'll want to wrap some important functionality *around* your state, not directly nested *inside* another component. In these cases, you'll want to pass elements and attributes into a component and let the component place them appropriately.
In this chapter, you'll learn about:
- Passing elements into components
- Passing attributes into components
## The use case
Let's say you're building a user interface and want to make some part of it clickable to another website. You would normally start with the HTML `` tag, like so:
```rust
rsx!(
a {
href: "https://google.com"
"Link to google"
}
)
```
But, what if we wanted to style our `` tag? Or wrap it with some helper icon? We could abstract our RSX into its own component:
```rust
#[derive(Props)]
struct ClickableProps<'a> {
href: &'a str,
title: &'a str
}
fn clickable(cx: Scope) -> Element {
cx.render(rsx!(
a {
href: "{cx.props.href}"
"{cx.props.title}"
}
))
}
```
And then use it in our code like so:
```rust
rsx!(
clickable(
href: "https://google.com"
title: "Link to Google"
)
)
```
Let's say we don't just want the text to be clickable, but we want another element, like an image, to be clickable. How do we implement that?
## Passing children
If we want to pass an image into our component, we can just adjust our props and component to allow any `Element`.
```rust
#[derive(Props)]
struct ClickableProps<'a> {
href: &'a str,
body: Element<'a>
}
fn clickable(cx: Scope) -> Element {
cx.render(rsx!(
a {
href: "{cx.props.href}"
{&cx.props.body}
}
))
}
```
Then, at the call site, we can render some nodes and pass them in:
```rust
rsx!(
clickable(
href: "https://google.com"
body: cx.render(rsx!(
img { src: "https://www.google.com/logos/doodles/2021/seasonal-holidays-2021-6753651837109324-6752733080595603-cst.gif" }
))
)
)
```
This pattern can become tedious in some instances, so Dioxus actually performs an implicit conversion of any `rsx` calls inside components into `Elements` at the `children` field. This means you must explicitly declare if a component can take children.
```rust
#[derive(Props)]
struct ClickableProps<'a> {
href: &'a str,
children: Element<'a>
}
fn clickable(cx: Scope) -> Element {
cx.render(rsx!(
a {
href: "{cx.props.href}"
{&cx.props.children}
}
))
}
```
And to call `clickable`:
```rust
rsx!(
clickable(
href: "https://google.com"
img { src: "https://www.google.com/logos/doodles/2021/seasonal-holidays-2021-6753651837109324-6752733080595603-cst.gif" }
)
)
```
> Note: Passing children into components will break any memoization due to the associated lifetime.
While technically allowed, it's an antipattern to pass children more than once in a component and will probably break your app significantly.
However, because the `Element` is transparently a `VNode`, we can actually match on it to extract the nodes themselves, in case we are expecting a specific format:
```rust
fn clickable(cx: Scope) -> Element {
match cx.props.children {
Some(VNode::Text(text)) => {
// ...
}
_ => {
// ...
}
}
}
```
## Passing attributes
In the cases where you need to pass arbitrary element properties into a component - say to add more functionality to the `` tag, Dioxus will accept any quoted fields. This is similar to adding arbitrary fields to regular elements using quotes.
```rust
rsx!(
clickable(
"class": "blue-button",
"style": "background: red;"
)
)
```
For a component to accept these attributes, you must add an `attributes` field to your component's properties. We can use the spread syntax to add these attributes to whatever nodes are in our component.
```rust
#[derive(Props)]
struct ClickableProps<'a> {
attributes: Attributes<'a>
}
fn clickable(cx: Scope) -> Element {
cx.render(rsx!(
a {
..{cx.props.attributes},
"Any link, anywhere"
}
))
}
```
The quoted escapes are a great way to make your components more flexible.
## Passing handlers
Dioxus also provides some implicit conversions from listener attributes into an `EventHandler` for any field on components that starts with `on`. IE `onclick`, `onhover`, etc. For properties, we want to define our `on` fields as an event handler:
```rust
#[derive(Props)]
struct ClickableProps<'a> {
onclick: EventHandler<'a, MouseEvent>
}
fn clickable(cx: Scope) -> Element {
cx.render(rsx!(
a {
onclick: move |evt| cx.props.onclick.call(evt)
}
))
}
```
Then, we can attach a listener at the call site:
```rust
rsx!(
clickable(
onclick: move |_| log::info!("Clicked"),
)
)
```
Currently, Dioxus does not support an arbitrary amount of listeners - they must be strongly typed in `Properties`. If you need this use case, you can pass in an element with these listeners, or dip down into the `NodeFactory` API.
## Wrapping up
In this chapter, we learned:
- How to pass arbitrary nodes through the tree
- How the `children` field works on component properties
- How the `attributes` field works on component properties
- How to convert `listeners` into `EventHandlers` for components
- How to extend any node with custom attributes and children
Next chapter, we'll talk about conditionally rendering parts of your user interface.