Html
Html elements are the building blocks of web pages. While other rust frameworks aim for a JSX-like syntax, this library uses a more traditional approach. The goal is to provide a simple and efficient way to create HTML elements without the need for complex syntax, we use the idomatic rust builder pattern.
Natrix uses a single HtmlElement
struct to represent all HTML elements. But exposes helper functions for each tag.
These are found along side the HtmlElement
struct in the html_elements
module.
Which will most commonly be used via the e
alias in the prelude
module.
extern crate natrix;
use natrix::prelude::*;
let _: e::HtmlElement<(), _> =
e::div()
;
If you need to construct a element with a tag not found in the library you can use HtmlElement::new
.
extern crate natrix;
use natrix::prelude::*;
let _: e::HtmlElement<(), ()> =
e::HtmlElement::new("custom_tag")
;
Children
Children are added using the .child
method. This method takes a single child element and adds it to the parent element.
extern crate natrix;
use natrix::prelude::*;
let _: e::HtmlElement<(), _> =
e::div()
.child(e::button())
.child(e::h1().child("Hello World!"))
;
Child elements can be any type that implements the Element
trait, including other HtmlElement
instances, and stdlib types like String
, &str
, i32
, as well as containers such as Option
and Result
.
Child elements can also be reactive as closures implement the Element
trait.
extern crate natrix;
use natrix::prelude::*;
#[derive(Component)]
struct MyComponent {
pub is_active: bool,
}
impl Component for MyComponent {
fn render() -> impl Element<Self> {
e::div()
.class("my-component")
.child(e::button()
.text("Click me!")
.on::<events::Click>(|ctx: E<Self>, _| {
*ctx.is_active = !*ctx.is_active;
})
)
.child(|ctx: R<Self>| {
if *ctx.is_active {
Some(e::p().text("Active!"))
} else {
None
}
})
}
}
Attributes
Attributes are set using the .attr
method. This method takes a key and a value, and sets the attribute on the element.
extern crate natrix;
use natrix::prelude::*;
let _: e::HtmlElement<(), _> =
e::div()
.attr("data-foo", "bar")
.attr("data-baz", "qux")
;
Most standard html attributes have helper functions, for example id
, class
, href
, src
, etc.
For non-global attributes natrix only exposes them on the supporting elements.
extern crate natrix;
use natrix::prelude::*;
let _: e::HtmlElement<(), _> =
e::a()
.href("https://example.com")
.target("_blank")
.rel("noopener noreferrer")
;
But the following wont compile:
extern crate natrix;
use natrix::prelude::*;
let _: e::HtmlElement<(), _> =
e::div()
.target("_blank") // error: no method named `target` found for struct `HtmlElement<_, _div>`
;
Attributes can be set by anything that implements the ToAttribute
trait, this includes numberics, Option
, and bool
, and others.
Attributes can also be reactive as closures implement the ToAttribute
trait.
extern crate natrix;
use natrix::prelude::*;
#[derive(Component)]
struct MyComponent {
pub is_active: bool,
}
impl Component for MyComponent {
fn render() -> impl Element<Self> {
e::button()
.class("my-button")
.disabled(|ctx: R<Self>| !*ctx.is_active)
.text("Click me!")
.on::<events::Click>(|ctx: E<Self>, _| {
*ctx.is_active = !*ctx.is_active;
})
}
}
Classes
The .class
method is not a alias for .attr
, it will add the class to the element, and not replace it. This is because the class
attribute is a special case in HTML, and is used to apply CSS styles to elements. The .class
method will add the class to the element, and not replace any existing ones.
extern crate natrix;
use natrix::prelude::*;
let _: e::HtmlElement<(), _> =
e::div()
.class("foo")
.class("bar")
.class("baz")
;