Mutable maps

The MutableBTreeMap type provides an observable container with map semantics, much the same way MutableVec provides vector semantics.

The ideas are fairly similar to what we already covered for MutableVec, but there are more ways to get signals for the map entries than there are for the mutable vector.

SignalVec of keys and entries

Let's first look at the signal_vec_keys() and signal_vec_entries() methods. They give us a SignalVec<Item=Key> and SignalVec<Item=(Key,Value)> respectively. They will only update at indexes corresponding to keys for which a value was inserted, changed or removed in the map.

let mutable_map: MutableBTreeMap<String, String> = MutableBTreeMap::new();

// Gives us a signal vec of all the keys in the map
let keys_signal = mutable_map.signal_vec_keys().map(|key| {
    html!("div", {
        .text(&key)
    })
});

// Gives a signal vec of all the (key, value) entries in the map
let entries_list_signal = mutable_map.entries_cloned().map(|(key, value)| {
    html!("dom", {
        .text(&format!("{key}: {value}"))
    })
});

html!("div", {
    .children_signal_vec(keys_signal)
    .children_signal_vec(entries_list_signal)
})

Get a signal to the value for a specific key

We sometimes want to show the value for a key, if it is in the map at all. The signal_map().key_cloned(key) method will give us just that; a signal to whatever (if any) value exists in the map for the specified key.

In the following example, we transform the key_cloned() signal for the key "my-key" to a signal of String, which we insert into the dom as text.

let mutable_map: MutableBTreeMap<&str, String> = MutableBTreeMap::new();

// Get a signal for the optional value for a given key in the map
let key_signal = mutable_map
    .signal_map_cloned()
    .key_cloned("my-key")
    .map(|value: Option<String>| {
        match value {
            Some(v) => format!("my-key has value: {v}"),
            _ => "my-key has no value in the map".to_string()
        }
    }
);

html!("div", {
    .text_signal(key_signal)
})

Maps of mutables

Sometimes, you have a mutable map that holds mutable values. In those cases, you'll may wish to get a signal that covers both entries changing in the map, and when their corresponding values change.

For this, you can use 'map_value_signal()'. It allows you to essentially flatten the map_signal and a signal derived from the values of the elements!

// A map with mutable values
let mutable_map: MutableBTreeMap<&str, Mutable<String>> = MutableBTreeMap::new();

// Get a map signal that updates both when keys and their corresponding value signal changes
let key_signal = mutable_map
    .signal_map_cloned()
    .map_value_signal(|value: Mutable<String>| value.signal_cloned())
    .key_cloned("some-key")
    .map(|v| {
        v.unwrap_or("no-value".to_string())
});

html!("div", {
    .text_signal(key_signal)
})