Code Monkey home page Code Monkey logo

observable_ish's Introduction

observable_ish

Write elegant reactive cross-platform client side application using observable states and event emitters.

Provides:

  1. Reactive Values
  2. Reactive Lists
  3. Reactive Sets
  4. Reactive Maps
  5. Event emitter

Philosophy

Observable-ish provides a light-weight non-intrusive reactive framework to build cross-platform UI. It uses Dart's asynchronous Streams 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:

  1. onChange: Record of changes
  2. values: Stream of new values
  3. listen: Callback function with new value
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

Emitters 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

  1. on: Execute callback on event
  2. listen: Similar to Stream
  3. asStream: Obtain event as Stream

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 bools or RxValue of bools.

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.

observable_ish's People

Contributors

aabccd021 avatar tejainece avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

observable_ish's Issues

RxMap onChange Listener

How does one listen for changes for an RxMap?

The docs say

Listening for changes: onChange exposes a Stream of record of change of the Map.

But the RxMap Class docs don't show an onChange, and my editor shows:

	"code": "undefined_getter",
	"message": "The getter 'onChange' isn't defined for the type 'RxMap<dynamic, dynamic>'.\nTry importing the library that defines 'onChange', correcting the name to the name of an existing getter, or defining a getter or field named 'onChange'."

I just updated to version 3, but I couldn't figure this out on version 2 either.

Thanks for any insights.

Initial value not optional

In the latest version, I always have to provide an initial value. Can we make the initial value as optional ?

Breaking Changes

Was just wondering if there is a log of the breaking changes? pub.dev just shows, "Breaking changes: Be aware, there are some breaking changes!" but no link. I've got 82 new errors I need to fix. ๐Ÿ˜„ Thank you for any insights!

Non-reactive "Reactive" Maps.

RxMaps simply does not work when used. If there is a special way to use it then it does not appear to be in the docs.

Observer widget

Currently we have only Rx types.
But your package does not provide anything to rebuild state.
So the only way is to convert Rx variables to streams and to build it with StreamBuilder (looks awkward).
GetX (based on your package) has Obx widget which works like
Obx ( () => Text ( counter.value ) ),

Please add the widget named Observer with the same functionality out of the box, so we wouldn't need StreamController or third-party solutions.

Don't update the value

I don't understand why in this version it doesn't update
stacked: ^2.0.2
stacked_services: ^0.8.1
injectable: ^1.2.2
observable_ish: ^3.0.0

`
RxValue<String?> _fullname = RxValue<String?>(null);
.....
_fullname.value = 'test'; <--- work after
User user = await _firestoreService.getUser(uid);
_fullname.value = user.name; <--- not work

`

I don't update the value after await
someone has the same problem as me in the null-safety version?

Support for Null-Safety

Hello!, I wanted to know if there is any plans for null-safety as the package I'm trying to migrate depends on this.
If there's any help required I'm willing to make a PR for the same!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.