Views
Sycamore uses the view!
macro as an ergonomic way to create complex user interfaces. You might
have already seen it in the “Hello, World!” example.
Dislike macros? Check out the alternative builder pattern.
view! Syntax
Write your markup inside the view!
macro and get a View
expression.
Elements
Creating HTML elements is easy as pie with the view!
macro. Since you’ll likely want to create a
lot of elements in your app, there is a special terse syntax.
view!
Text nodes
Of course, in your app, you probably want to display some text. To create a text node, simply add a string literal.
view!
Nesting
Creating all these top-level nodes is not very useful. You can create nested nodes like so.
view!
Interpolation
Views can contain interpolated values. Anything that implements std::fmt::Display
will
automatically be inserted as text into the DOM tree. For example:
let my_number = 123;
view!
Other views created using the view!
macro can also be interpolated using the same syntax. For
example:
let inner_view = view! ;
let outer_view = view! ;
The cool thing about interpolation in Sycamore is that it is automatically kept up to date with the value of the expression. Learn more about this in Reactivity.
Attributes
Attributes (including classes and ids) can also be specified.
view!
dangerously_set_inner_html
The special dangerously_set_inner_html
attribute is used to set an HTML string as the child of an
element. This should generally be avoided because it is a possible security risk. Never pass user
input to this attribute as that will create an XSS (Cross-Site Scripting) vulnerability.
view!
Instead, when displaying user input, use interpolation syntax instead.
Properties
Properties are set using the prop:*
directive.
view!
There are some properties that do not have an attribute, such as
indeterminate
in HTML, which must be set using the prop:*
directive.
There are a number of properties that have an associated attribute, such as
value
, in these cases an attribute is deserialized to become the state of the
property. Consider using the prop:*
for these cases when the value expected by
the element property is not a string
.
Events
Events are attached using the on:*
directive.
view!
Fragments
As seen in previous examples, views can also be fragments. You can create as many nodes as you want at the top-level.
view!
Fragments can also be empty. (Note that passing the cx
variable is still required. This
restriction will be lifted in the future.)
view!
Builder syntax
For those who dislike macro DSLs, we also provide an ergonomic builder API for constructing views. Add the builder prelude as well as the main sycamore prelude to your source file.
use *;
use *;
Elements
Elements can easily be created using the utility h
function.
a
button
div
// etc...
Observe that this creates an ElementBuilder
. This is a struct used for lazily constructing the
element. To get a View
from an ElementBuilder
, just call .view(cx)
at the end of the builder
chain. This will evaluate all the lazy builder calls preceding it by passing in cx
.
Text nodes
Text nodes are created using the t
function.
t
This function does not return an ElementBuilder
(because text nodes are not elements!) and instead
directly gives you a View
.
Nesting
Nodes can be nested under an element using a combination of .c(...)
for child element nodes and
.t(...)
for child text nodes.
div .c
Interpolation
Dynamic values are inserted using .dyn_c(...)
and .dyn_t(...)
instead of .c(...)
and .t(...)
respectively.
let my_number = 123;
p
.t
.dyn_t
Attributes
Unsurprisingly, attributes can also be set using the builder pattern.
p .attr .attr .attr
For convenience, the methods .class(...)
and .id(...)
are provided for setting the class
and
id
attributes directly. This means that we can rewrite our previous example as:
p .class .id .attr
dangerously_set_inner_html
At this time, the special dangerously_set_inner_html
attribute from the view!
macro is not
supported by the builder API.
Events
Events are attached using .on(...)
.
button .on .t
Fragments
Construct fragments using fragment(...)
.
fragment