Skip to content
Frontend frame-work for wasm on Rust.
Rust
Branch: master
Clone or download
SoundRabbit Merge pull request #34 from SoundRabbit/develop/SoundRabbit
Update component.rs to fix bug: the message sended by initial cmd was…
Latest commit e14ea29 Nov 30, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
docs
src
.gitignore
Cargo.lock
Cargo.toml
LICENSE-AP
LICENSE-MIT
README.md
kagura.png

README.md

logo

Kagura

A front-end framework that runs on WebAssembly written in Rust.

Big changes

  • Supporting a batch process
  • Experimental supporting of websocket

Tutorial

In English

tutorial

In Japanese

[Kagura] Kagura + Rust でWebページを作成

Hello World

extern crate kagura;
extern crate wasm_bindgen;

use kagura::prelude::*;
use wasm_bindgen::prelude::*;

#[wasm_bindgen(start)]
pub fn main() {
    kagura::run(Component::new(init, update, render), "app");
}

struct State;

struct Msg;

struct Sub;

fn init() -> State {
    State
}

fn update(_: &mut State, _: Msg) -> Cmd<Msg, Sub> {Cmd::none()}

fn render(_: &State) -> Html<Msg> {
    Html::h1(
        Attributes::new(),
        Events::new(),
        vec![
            Html::text("hello kagura"),
        ],
    )
}

Usage

Create component

kagura::Component::new(init, update, render)

init, update and render is function :

init : fn() -> State
update : fn(&mut State, Msg) -> Cmd<Msg, Sub>
render : fn(&State) -> Html<Msg>

Set a component to application

kagura::run(component, id_of_entry_point_in_html)

Render Element

kagura::Html::html_tag(attributes, events, children)

attributes : instance of kagura::Attributes

events : instance of kagura::Events

children : Vec<Html>

Example

<ul class="list example" id="my-list" data-fizz="bazz">
    <li>foo</li>
    <li>bar</li>
    <li>baz</li>
</ul>

is made by

use kagura::Html;
use kagura::Attributes;
use kagura::Events;

Html::ul(
    Attributes::new()
        .class("list")
        .class("example")
        .id("my-list")
        .string("data-fizz", "bazz"),
    Events::new(),
    vec![
        Html::li(Attributes::new(), Events::new(), vec![Html::unsafe_text("foo")]),
        Html::li(Attributes::new(), Events::new(), vec![Html::unsafe_text("bar")]),
        Html::li(Attributes::new(), Events::new(), vec![Html::unsafe_text("baz")])
    ]
)

Render Component

kagura::Html::component(component)

component : instance of kagura::Component

Transmit message to a parent component

update can send message to parent compoent as Some(message).

Receive child message and bind to own message

component.subscribe(impl: Sub -> Box<Any>) can receive message from child component and bind to own message.

Example

fn render() -> Html<Msg> {
    Html::component(
        child_component::new().subscribe(|sub| match sub {
            child_component::Sub::Foo => Msg::Bar
        })
    )
}

mod child_component {
    fn new() -> Component<Msg, State, Sub> {
        Component::new(initial_state, update, render)
    }

    .
    .
    .
}

Cmd

Cmd::none()

Cmd::none() means nothing to do. If you return Cmd::none(), kagura will render.

Cmd::sub(sub: Sub)

If you send sub-message to parent component, use this.

Cmd::task(task: impl FnOnce(Resolver<Msg>) + 'static)

You can use this feature like callback function in JavaScript. like this:

fn update(state: &mut State, msg: Msg) -> kagura::Cmd<Msg, Sub> {
    use kagura::Cmd;
    match msg {
        Msg::ChangeMessage(message) => {
            state.message = message;
            Cmd::none()
        }
        Msg::ChangeMessageTask(message) => Cmd::task(|resolver| {
            let resolver = Closure::once(|| resolver(Msg::ChangeMessage(message)));
            web_sys::window()
                .unwrap()
                .set_timeout_with_callback_and_timeout_and_arguments_0(
                    resolver.as_ref().unchecked_ref(),
                    1000,
                );
            resolver.forget();
        }),
    }
}

Batch

You can set a batch process to component like this:

Component::new(init, update, render)
    .batch(batch::time::tick(1000, || Msg::SomeMsg))
You can’t perform that action at this time.