Making Siblings

We've so far seen how to render HTML elements and nest them.

But how do we put elements side-by-side?

<input />
<input />

In the Building Nested HTML subchapter, we learned that UI elements only stay on screen for as long as their corresponding Future is running. Thus, if we want two elements on the screen at once, we'll need to run two Futures concurrently.

To run Futures concurrently, we "join" them. The join function takes in multiple Futures, and return a single Future. When awaited, the returned Future will drive the input Futures to completion and return all their results.

#![allow(unused)]
fn main() {
use async_ui_web::{html::Input, join}; // 👈 get the `join` function
async fn two_inputs() {
    let input_1 = Input::new();
    let input_2 = Input::new();
    // 👇 join takes a tuple of Futures
    join((input_1.render(), input_2.render())).await;
}
}

A webpage with two empty input fields

Also, join is not limited to tuples of Futures. You can also pass it an array or a vector of Futures. See its documentation to learn more.

More complicated example

Let's render this HTML

<div>
	<button>Hello World</button>

	<span>1</span>
	<span>2</span>
	<span>3</span>
	<!-- more spans here -->
	<span>98</span>
	<span>99</span>
	<span>100</span>

	<input />
</div>
#![allow(unused)]
fn main() {
async fn lots_of_span() {
    Div::new() // the wrapping <div>
        .render(join((
            // the <button> at the top
            Button::new().render("Hello World".render()),
            // the 100 <span>s, made by joining a vec of 100 Futures
            join(
                (1..=100)
                    .map(|number| Span::new().render(number.to_string().render()))
                    .collect::<Vec<_>>(),
            ),
            // the <input> at the end
            Input::new().render(),
        )))
        .await;
}
}

That code looks pretty complicated ☚ī¸. But we can improve it! We'll split it into small, easy-to-understand parts in the next subchapter!