Get started
Let's get started with a simple project, which we'll get to know the basics of Floem.
Create a new Rust project
Adding Floem dependency
Hello World
In your main.rs, put the following
And then, cargo run
will give you your first hello world in a Floem window.
That looks simple, isn't it? If you look at the definition of floem::launch
, you'll find that it takes a closure which returns a IntoView
. If you're familiar with Rust, IntoView
is a trait with method into_view
where you can convert any type that implements the trait to a Floem View
. A Floem View
is the core of Floem, where it can be a text label, a button, a text input, or a scroll etc. And Floem implements IntoView
for &str
type internally, so we can directly return "Hello, World!" as a IntoView
.
Now let's dive in to a more complex example, a counter app.
Counter App
We'll create a very simple counter, where it shows the current counter value, a increment button, a decrement button.
In main.rs, put the following.
Run this, and you should be able to see "Value: " and two giant buttons for "Increment" and "Decrement".
Let's improve it by giving our example a bit of "style"
If you run it again, you should see it should be properly laid out. And in Floem, the views are styled by style
method, where it's provided by floem::views::Decorators
to any type that's a IntoView
type. So remember to import the trait first otherwise Rust compiler will shout at you.
Floem style is a Rust implementation of web Flexbox via the Taffy crate. So you should find lots of similar things if you're already familiar with Flexbox. If you're not, there're lots of guides and tutorials online that talk about Flexbox, and they should be transferrable to Floem styles.
Reactivity
But it doesn't do anything when you click the buttons. That's because there's no value that's been changed or displayed yet. How do you achieve reactivity in Floem?
Signal
will be the primitive for reactivity in Floem. If you're familiar with Solidjs or Leptos, that would be similar to the signal in those frameworks. Simply put, if you update the value of a Signal
, anything that "listens" to signal will get notified and trigger an action based on the update. In our counter example, we want the counter value gets updated in the UI. So let's create a signal.
The first thing you'll notice is we created a counter signal. And we wrapped up the value display in a dyn_view
with a closure which formats the counter value. You might want to ask why not simply a format!("Value: {}", counter)
since String should impl IntoView
. Well, that will compile without errors, but we loose the reactivity if we do that way.
Let me explain.
Unlike frameworks like Reactjs, the view creation function is only called once. So format!("Value: {}", counter)
will only be called once too, and it will take the initial value of counter which is 0. Even when we update the value of counter signal later in the application, the Value: 0
won't get updated because we won't run that again.
So reactivity in Floem relies on closures, and we will run the closure again and again whenever the signal gets updated. And that provides the characteristic of "fine grained reactivity" in Floem, where the UI doesn't need to do a diff with the previous state, but can only update what needs to be updated, no matter how deep a particular view is at in the view tree. Assume the counter value display in our example is deeply at a nested place, we can still "directly" update the UI, and only that text label part of the UI, without traverse the view tree from the root.
And that gives a basic rule of reactivity in Floem. If you want something to be updated, you'll need to use a closure. So if you ever encounter a bug using Floem where something doesn't get updated, the first thing you'll need to check is "is it a closure"?
Action
But still the buttons don't do anything. That's because we haven't let the button click to update the counter signal yet. And if you do this
So we simply let action
method on the buttons to increment or decrement the value of counter signal. Now you should have a working counter example.
This will conclude our getting start tutorial. To learn more about Floem, you can check out the examples in our repo, or read the API docs.
Last updated