observable_ish 4.0.8 observable_ish: ^4.0.8 copied to clipboard
Write elegant reactive cross-platform client side application using observable states and event emitters.
observable_ish #
Write elegant reactive cross-platform client side application using observable states and event emitters.
Provides:
Philosophy #
Observable-ish provides a light-weight non-intrusive reactive framework to build cross-platform UI. It uses Dart's
asynchronous Stream
s to emit and listen to changes.
Various observable types like RxValue
, RxList
, RxSet
and RxMap
can be
used to update UI automatically on changes. Events can be passed up the widget tree using event Emitter
.
Reactive values #
RxValue
can be used to encapsulate a simple observable value.
Getting and setting value #
RxValue
exposes field value
to get set current value.
main() {
final rxInts = RxValue<int>(initial: 5);
int got = rxInts.value; // Gets current value
rxInts.value = 10; // Sets current value
}
When a value that is different from the existing value is set, the change is notified through various ways explained in the section.
Listening to changes #
It provides few flexible ways to listen to changes:
main() {
final rxInts = RxValue<int>(initial: 5);
print(rxInts.value); // => 5
rxInts.values.listen((int v) => print(v)); // => 5, 20, 25
rxInts.value = 20;
rxInts.value = 25;
}
Binding to a value #
Binding an RxValue
to a Stream
(using method bindStream
) or another RxValue
(using method bind
) changes its value when the source Stream
emits or RxValue
changes. This is very
useful in scenarios where one would like to change a model's value or widget's property when control changes. For example,
change a text field's value when a checkbox is toggled.
textBox.value.bindStream(checkBox.checked.map((bool v) => v?'Female': 'Male'));
Full examples #
main() {
final rxInts = RxValue<int>(initial: 5);
print(rxInts.value); // => 5
rxInts.value = 10;
rxInts.value = 15;
rxInts.values.listen((int v) => print(v)); // => 15, 20, 25
rxInts.value = 20;
rxInts.value = 25;
}
Composite reactive objects #
Observable-ish is designed to be non-intrusive. The philosophy is to separate the model and its reactive cousin into different classes.
class RxUser {
final name = RxValue<String>();
final age = RxValue<int>();
}
class User {
final rx = RxUser();
User({String name, int age}) {
this.name = name;
this.age = age;
}
String get name => rx.name.value;
set name(String value) => rx.name.value = value;
int get age => rx.age.value;
set age(int value) => rx.age.value = value;
}
main() {
final user = User(name: 'Messi', age: 30);
user.age = 31;
print(user.age); // => 31
print('---------');
user.age = 32;
user.rx.age.listen((int v) => print(v)); // => 20, 25
user.age = 33;
user.age = 34;
user.age = 35;
}
Event emitter #
Emitter
s provide a simple interface to emit and listen to events. It is designed to inter-operate with RxValue
to provide
maximum productivity.
Listening to a event #
Piping events #
pipeTo
pipes events to another Emitter
.
pipeToValue
pipes events to the given RxValue
. This could be very helpful in binding events
to observable values.
Emitting events #
emit
, emitOne
, emitAll
, emitStream
and emitRxValue
provides various ways to emit events using the Emitter
Reactive Lists #
RxList
notifies changes (addition, removal, clear, setting) of its elements.
Updating RxList #
RxList
implements Dart's List
.
Besides List
's methods, RxList
provides convenient methods like addIf
and addAllIf
to add elements based on a condition. This is very useful in writing UI in Dart DSL (as in Flutter and Nuts).
main() {
final rxInts = RxList<int>();
rxInts.onChange.listen((c) => print(c.element)); // => 5
rxInts.addIf(5 < 10, 5);
rxInts.addIf(5 > 9, 9);
}
Use assign
and assignAll
methods to replace existing contents of the list with new content.
Listening for changes #
onChange
exposes a Stream
of record of change of the List
.
Reactive Sets #
RxSet
notifies changes (addition and removal) of its elements.
Updating RxSet #
RxSet
implements Dart's Set
.
Besides Set
's methods, RxSet
provides convenient methods like addIf
and addAllIf
to add elements based on a condition. This is very useful in writing UI in Dart DSL (as in Flutter and Nuts).
main() {
final rxInts = RxSet<int>();
rxInts.onChange.listen((c) => print(c.element)); // => 5
rxInts.addIf(5 < 10, 5);
rxInts.addIf(5 > 9, 9);
}
Listening for changes #
onChange
exposes a Stream
of record of change of the Set
.
Binding #
bindBool
and bindBoolValue
allows removing or adding the given element based on the Stream
of
bool
s or RxValue
of bool
s.
bindOneByIndexStream
and bindOneByIndex
allows removing all but the one element from a given Iterable
of elements based on index Stream
or RxValue
.
Reactive Maps #
RxMap
notifies changes (addition, removal, clear, setting) of its elements.
Updating RxMap #
RxMap
implements Dart's Map
.
Besides Map
's methods, RxMap
provides convenient methods like addIf
and addAllIf
to add elements based on a
condition. This is very useful in writing UI in Dart DSL (as in Flutter and Nuts).
Listening for changes #
onChange
exposes a Stream
of record of change of the Map
.