Combining values

computed_tuple!

To derive something from several values, combine them with computed_tuple!. It creates a Computed of a tuple, which can be mapped further:

    use vertigo::{bind, computed_tuple, dom, Value};

    let price = Value::new(120);
    let quantity = Value::new(2);

    // Recomputed whenever any of the values changes
    let total = computed_tuple!(price, quantity).map(|(price, quantity)| price * quantity);

    let one_more = bind!(quantity, |_| quantity.change(|quantity| *quantity += 1));

    dom! {
        <div>
            <p>{price} " x " {quantity} " = " {total}</p>
            <button on_click={one_more}>"One more"</button>
        </div>
    }

Computed::from

For any other logic, create a Computed from a closure. Values are read through ctx, and every value read that way becomes a dependency:

    use vertigo::{bind, dom, Computed, Value};

    let first_name = Value::new("Ada".to_string());
    let last_name = Value::new("Lovelace".to_string());
    let show_full = Value::new(true);

    // Every value read through `ctx` becomes a dependency
    let display_name = Computed::from(bind!(first_name, last_name, show_full, |ctx| {
        if show_full.get(ctx) {
            format!("{} {}", first_name.get(ctx), last_name.get(ctx))
        } else {
            first_name.get(ctx)
        }
    }));

    let toggle = bind!(show_full, |_| show_full.change(|show| *show = !*show));

    dom! {
        <div>
            <p>"Hello, " {display_name}</p>
            <button on_click={toggle}>"Toggle full name"</button>
        </div>
    }

Dependencies are collected anew on every run, so above last_name is watched only while the full name is shown.

Only real changes are propagated

A Computed notifies about a change only when its new value differs from the previous one (that's why it requires PartialEq). So for example price.map(|price| price > 100) updates the page only when the price crosses 100, not on every change of the price.