Saturday, March 1, 2014

Different Ways to Listen to Polymer Property Changes in Dart


It still bothers the heck out of me I cannot write Polymer observe blocks in my Dart Polymers.

In JavaScript, if I want to update a value when another value is updated, I can call an appropriate “sync” method via observe block:
Polymer('hello-you', {
  // ...
  observe: {'balloon_count': '_syncBalloonCount'},
  _syncBalloonCount: function() {
    // do synchronization stuff here...
  },
  // ...
});
In Dart, however, establishing the same thing:
@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  // ...
  Map observe = {'count': '_syncBalloonCount'};
  _syncBalloonCount() {
    labels['__count__'] = count;
  }
  // ...
}
Has no effect. I have tried this on a couple of occasions with limited success—and nothing that would cover this case.

After the previous nights' adventures, I wound up watching for all changes on my custom <hello-you> Polymer, then filtering out everything but changes to the count attribute:
@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  // ...
  enteredView() {
    super.enteredView();
    changes.listen((list){
      list.
        where((r)=> r.name == #count).
        forEach((_){ _syncBalloonCount() });
    });
  }
  // ...
}
But that is 4 lines of code and a heck of a lot less readable than the observe block in JavaScript.

I come to the realization that “changed” methods will do the trick:
@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  // ...
  countChanged(o, v)=> _syncBalloonCount();
  // ...
}
Based on the code samples currently in Patterns in Polymer, I am unsure if I realized that worked in Dart before tonight. Even tonight, it took a bit of trial and error to realize that it does work—those two parameters (old and new value)—are required. If omitted, the countChanged() callback is not invoked.

That will likely wind up being the best option for me in this particular case. Before calling it a night. I also try out the PathObserver. That too will likely be a nice addition to my Dart Polymer toolbox as I can achieve my goal in two lines:
@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  // ...
  enteredView() {
    super.enteredView();

    PathObserver observer = new PathObserver(this, 'count');
    observer.changes.listen((_)=> _syncBalloonCount());
  }
  // ...
}
That, or a CompoundPathObserver:
    // ...
    var observer = new CompoundPathObserver()
      ..addPath(this, 'count');
    observer.changes.listen((_)=> _syncBalloonCount());
    // ...
Seem like they could be very handy in certain circumstances.

I still think that I might appreciate having an observe block available, but am much happier with these additions to the list of ways that I can watch a single value change. Each is much preferable to the filtered stream I had been using.


Day #1,041

No comments:

Post a Comment