#functional #gui #ui-framework #web-ui

consecuit_html

HTML components for the Consecuit web UI framework

2 unstable releases

0.2.0 Jun 25, 2021
0.1.0 Jun 24, 2021

#49 in #web-ui

LGPL-2.1

370KB
9K SLoC

Consecuit HTML


lib.rs:

HTML components for [consecuit].

This crate provides components like div, span, table for [consecuit].

Basic usage

Also see the docs at [consecuit], as it also contain some info on how to use this.

First, import the prelude:

use consecuit_html::prelude::*;

Then you can use the components in the cc_tree! macro with the same structure as HTML:

cc_tree!(
<div>
<div>
</div>
</div>
<span>"hello"</span>
)

Props

All components in this crate takes props that can be built with builder pattern.

Start with [html_props()][elem::html_props()], then add your attributes. Like this:

cc_tree!(
<div {html_props().class_name("container container-box").onclick(click_handler)}>
</div>
)

String attributes like class_name or href take anything that is Into<Cow<'static, str>>. In the code above, class_name can take "container container-box" because it is &'static str which is Into<Cow<'static, str>>.

Event attributes like onclick or oninput take a Callback. A Callback can be created with Callback::new, like this:

let click_handler = Callback::new(move |ev: web_sys::MouseEvent| {
web_sys::console::log_1(
&"You clicked the button!".into()
);
});

cc_tree!(
<button {html_props().onclick(click_handler)}>"click me!"</button>
)

Sometimes you may get error about ambigous props. For example, many different components take href. The compiler won't allow this:

<a {html_props().href("https://example.com")}>"Go to web"</a>

You have to use HtmlProps<(web_sys type of your element)> instead. For example:

<a {HtmlProps::<web_sys::HtmlAnchorElement>::new().href("https://example.com")}>"Go to web"</a>

Reference

To get a reference to the underlying [web_sys] element, you can use the reference prop.

The reference prop takes a Reference of Option of the element type. For instance, the input tag (<input>) has web_sys::HtmlInputElement as the underlying element. So its reference must be a Reference<Option<web_sys::HtmlInputElement>>.

let (cc, input_ref): (_, Reference<Option<web_sys::HtmlInputElement>>) = cc.hook(use_ref, ());
cc_tree!(
<input {html_props().reference(input_ref)} />
)

The Option inside the reference is guarunteed to be Some after the component rendered atleast once.

You can then use the methods in Reference to do things with the underlying [web_sys] element.

For example, this read the value of an and set it to empty.

let (cc, input_ref): (_, Reference<Option<web_sys::HtmlInputElement>>) = cc.hook(use_ref, ());
let submit_click_handler = Callback::new(move |_ev| {
let input_value = input_ref.visit_with(|opt: &Option<web_sys::HtmlInputElement>| {
// Unwrap the Option<web_sys::HtmlInputElement>
let inp: &web_sys::HtmlInputElement = opt.as_ref().unwrap();

// Get the value
let value = inp.value();

// Set it to empty
inp.set_value("");

value
}).unwrap();
web_sys::console::log_1(&format!("The submitted value was: {}", input_value).into());
});

cc_tree!(
<input {html_props().reference(input_ref)} />
<button {html_props().onclick(submit_click_handler)}>"submit"</button>
)

Notes

Most of the components and props in this crate are generated by a combination of parsing [web_sys]'s API and scraping MDN.

Only attributes with a set_ method provided by [web_sys] are available as props. For example, [web_sys] has set_class_name, so we have class_name prop.

Most notably missing is styling. [web_sys] does not have set_style. (it has a more sophisicated system for styling). You have to stick with class names and CSS for now.

Contributions are welcome.

Dependencies

~11MB
~220K SLoC