Skip to content

Commit

Permalink
docs: explain a workaround for if with typed children
Browse files Browse the repository at this point in the history
  • Loading branch information
ctron committed Dec 13, 2023
1 parent 1d88934 commit 23debb4
Showing 1 changed file with 93 additions and 0 deletions.
93 changes: 93 additions & 0 deletions website/docs/concepts/html/conditional-rendering.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,96 @@ html! {

</TabItem>
</Tabs>

## Using typed children

Assuming you have a component which uses `ChildrenRenderer<T>` or `ChildrenWithProps<T>`, it is currently not possible
to use the `if` syntax. However, as it is possible to use an `Iterator<T>` and `Option<T>` implements the iterator trait
in Rust, this can be transformed into using `for` instead.

Assuming you have the following component structure, `Parent` only accepting children of the type `Child`:

```rust
use yew::prelude::*;

#[function_component(Child)]
fn child() -> Html {
html! {}
}

#[derive(PartialEq, Properties)]
struct ParentProperties {
pub children: ChildrenWithProps<Child>,
}

#[function_component(Parent)]
fn parent(props: &ParentProperties) -> Html {
html! {}
}
```

Then it is possible to compose the children using `for`, translating the `bool` condition into an `Option` using
`Option::then`:

<Tabs>
<TabItem value="typed-children-valid" label="Using for">

```rust
use yew::prelude::*;

// component definition

#[function_component(Child)]
fn child() -> Html { html! {} }

#[derive(PartialEq, Properties)]
struct ParentProperties {
pub children: ChildrenWithProps<Child>,
}

#[function_component(Parent)]
fn parent(props: &ParentProperties) -> Html { html! {} }

// Making use of the `for` construct

#[function_component(Example)]
fn example() -> Html {
let condition = true; // or false

html! {
<Parent>
<Child /> // first child
<Child /> // second child
{ for condition.then(|| html_nested!(
<Child /> // optional third child
)) }
</Parent>
}
}
```

</TabItem>

<TabItem value="typed-children-invalid" label="Invalid">

What does not work is to use the `if` keyword directly, as it turns the component into an untyped children, which
cannot be assigned to the typed children types.

```rust, compile_fail
use yew::prelude::*;
let condition = true; // or false
html! {
<Parent>
<Child />
<Child />
if condition {
<Child /> // optional third child
}
</Parent>
}
```

</TabItem>
</Tabs>

0 comments on commit 23debb4

Please sign in to comment.