简体   繁体   中英

Using observables in Dart for Angular2 change detection

In my Angular2 app, written in Dart, I have several services that track data shared between components that don't necessarily have any particular relation in the view. I need updates initiated by any component to be reflected in every component's display, I want the performance benefits of OnPush change detection, I need components to display values that may have been set before the component was created, and I want all of this to be accomplished with minimal boilerplate.

My research indicates that Observables might be what I need, but I've been unable to find clear answers on several points.

Is there an implementation of Observable in Dart that works well with Angular2?

Is an Observable meaningfully different from a Dart Stream? In particular does an Observable support getting the current value in addition to being notified about future updates?

Last but not least, assuming Observable meets my requirements, what would be the minimal syntax for declaring an Observable String property of a component, initializing it with an Observable retrieved from an injected service, displaying its value in the component's template (starting with a pre-existing value), and having updates to its value automatically mark the component for on push change detection?

If Observable does not work for this, how else should I do it? My current idea is using a custom Stream subclass that inserts the most recent value ahead of anything else a new listener receives, and sending that through the async pipe to handle extracting values from the stream and marking for change detection.

My ideal solution would look something like this in use:

@Injectable()
class MyService {
  @observable int health;
}

@Component(
    ...)
class MyComponent {
  @observable int health;
  MyComponent(MyService service) : health = service.health;
}

And in the template:

<span>{{health | async}}</span>

Or for truly ideal, though this would have to hook into Angular's template compilation somehow (maybe with a transformer? I haven't learned how those work yet):

<span>{{health}}</span>

And with just that, it would just work.

The custom solution I now have working isn't quite as convenient as that, but it's close.

For collections and classes you can use https://pub.dartlang.org/packages/observe . It is not especially designed to be used with Angular2, rather for Polymer <= 0.16.x but it should work well with Angular2 OnPush .

If you make a collection observable

List myList = toObservable([]);

you can subscribe to changes

myList.changes.listen((record) {
  // invoke Angular change detection
});

When classes extend Observable (directly or by applying the Observable mixin)

class Monster extends Unit with Observable {
  @observable int health = 100;

  void damage(int amount) {
    print('$this takes $amount damage!');
    health -= amount;
  }

  toString() => 'Monster with $health hit points';
}

you also can subscribe to changes and notify Angular

var obj = new Monster();
obj.changes.listen((records) {
  // invoke Angular change detection
});

Note: If you have an observable collection with instances of observable classes, you need to listen to the collection and the containing classes individually. The collection only reports adds and removals but not property changes of the containing items.

Is an Observable meaningfully different from a Dart Stream? ...

I think Dart Observable is meaningful different from a Stream . someObservable.changes returns a Stream that emits the changes, but that change events are generated by the Observable implementation and the transformer that generates additional code from the @observable annotations on the properties.

In particular does an Observable support getting the current value in addition to being notified about future updates?

When you bind to the properties of an observable you get the current value. When values change and the changes subscription notifies about these changes and you notify Angular change detection that changes have happened, Angular will update the bindings to the recent values.

the minimal syntax for declaring an Observable String property of a component,

The above code example shows an int property but there is no difference when a String is used.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM