Lists, Maps and Sets
Live Cells provides extensions for cells holding List
s, Map
s and
Set
s, which allow the properties of the List
, Map
and Set
interfaces to be accessed directly on cells.
Indexing
For example the []
operator is overloaded for cells holding Lists
,
which allows a list element to be retrieved.
final list = MutableCell([1, 2, 3, 4]);
final index = MutableCell(0);
/// A cell which accesses the element at `index`
final element = list[index];
The element
cell retrieves the value of the element at index
within list
. You'll notice that the definition of the element
cell
looks exactly like retrieving the value of an element from an ordinary
List
. However, unlike an ordinarily List
element access, element
is a cell and its value will be recomputed whenever the list
and
index
, which is also a cell, change:
print(element.value); // 1
element.value = 2;
print(element.value); // 3
list.value = [3, 9, 27];
print(element.value); // 27
The element
cell is also a mutable cell which when set, updates the
value of the list
element at index
.
final list = MutableCell([1, 2, 3, 4]);
final index = MutableCell(0);
final element = list[index];
index.value = 1;
element.value = 100;
print(list); // 1, 100, 3, 4
The underlying List
is not modified but a new List
is created and
assigned to the list
cell.
You can also update the list
element directly using []=
:
list[1] = 100;
Unlike the []
operator, the index provided to the []=
operator is
a value not a cell.
Iterable Properties
Cells holding Iterable
values provide the following properties and
methods:
first
last
isEmpty
isNotEmpty
length
single
toList()
toSet()
Each property/method returns a cell which applies the property
getter/method on the Iterable
held in the cell. This allows you, for
example, to retrieve the first value in an Iterable
, be it a List
,
Set
, etc., held in a cell, using:
ValueCell<Iterable> seq;
...
final first = seq.first
This is roughly equivalent to:
final first = ValueCell.computed(() => seq().first);
cellList Property
The cellList
property, of cells holding Lists
, returns a cell
which evaluates to an Iterable
of cells, with each cell accessing
the value of an element in the original List
:
For example, consider the following cell:
// A list with four elements
final list = MutableCell([1, 2, 3, 4]);
list.cellList
returns a cell which holds the following list of cells:
final cellList = list.cellList;
// cellList.value is equivalent to the following:
[list[0], list[1], list[2], list[3]]
cellList
is reactive, like any other cell, and its value will
likewise change whenever the value of list
changes. So what's the
point? Unlike list
, cellList
only reacts to changes in the
length
of the list, i.e. when the number of elements in the list
change, and not the values of the elements themselves.
You can test this out using ValueCell.watch
:
ValueCell.watch(() {
print('${cellList().length} elements');
});
The following will not cause cellList
to be recomputed:
// Doesn't print anything since the
// number of elements hasn't changed
list.value = [5, 6, 7, 8];
list[0] = 100;
list[2] = -1;
However the following will cause cellList
to be recomputed:
// Prints: 3 elements
list.value = [1, 2, 3]
// Prints: 0 elements
list.value = [];
// Prints: 7 elements
list.value = [1, 2, 3, 4, 5, 6, 7];
This is particularly useful for constructing a Column
or Row
widget using a list of child widgets held in a cell:
ValueCell<List<Widget>> children;
CellWidget.builder((_) => Column(
children: children.cellList()
.map((c) => c.widget())
.toList()
);
The ValueCell.widget()
, available on cells holding Widget
s,
returns the Widget
held in the cell. Unlike retrieving the Widget
directly with .value
, the returned widget is rebuilt whenever the
value of the cell changes.
Here's what's going on in the example above:
children
is a cell holding the list of childWidgets
cellList
is used to retrieve a cell that is only recomputed when thelength
ofchildren
.- As a result the
CellWidget
, holding theColumn
, is only rebuilt, when the size ofchildren
changes. - The list (
Iterable
) of cells held incellList
is converted to a list ofWidgets
by applying thewidget()
method on each cell in the list.
As a result modifying an element of the children
list, will only
result in that child widget of the Column
being rebuilt and not the
entire widget hierarchy rooted at the Column
.
Map and Set Properties
The following properties and methods are provided by cells holding
Map
values:
entries
keys
values
isEmpty
isNotEmpty
length
containsKey()
containsValue()
Much like the with cells holding List
values, these properties and
methods return cells which apply the property getter/method on the
List
held in the cell.
The indexing operator []
is also provided, which takes a cell for the key:
final map = MutableCell({
'k1': 1,
'k2': 2,
'k3': 3
});
final key = MutableCell('k1');
final element = map[key];
print(element.value); // 1
element.value = 100;
print(map.value['k1']); // 100
key.value = 'k3';
print(element.value); // 3
key.value = 'not in map';
print(element.value); // null
Setting the value of a cell created by []
, updates the value of the
entry in the Map
cell. Like with cells holding List
s, the actual
Map
instance is not modified, but a new Map
, with the updated
entry, is created and assigned to the Map
cell.
The following methods are provided by cells holding Set
values:
contains
containsAll
Given that a Set
is an Iterable
, all the properties provided by
cells holding Iterables
are also provided by cells holding Sets
.