Tuesday, August 5, 2014

Does @ComputedProperty Make Observables?


I remain somewhat confused about the purpose of the @ComputedProperty annotation in the latest 0.12 release of Polymer.dart. I had planned on further exploring “timing” issues that may have necessitated this annotation, but Matthew Butler was kind enough to point me in a different direction. Specifically, he indicated that the primary utility of @ComputedProperty was that it marked its properties as observable.

I, being slightly dense, took this a little too literally. Given a @ComputedProperty of numToppings in child elements of <x-pizza>:
@CustomTag('x-pizza-toppings')
class XPizzaToppings extends PolymerElement {
  List<String> model = toObservable([]);

  @ComputedProperty("model.length")
  int get numToppings => readValue(#numToppings);

  int get numToppings_old => model.length;
  // ...
}
I first tried listening to changes to numToppings in the parent element's constructor:
@CustomTag('x-pizza')
class XPizza extends PolymerElement {
  // ...
  XPizza.created(): super.created() {
    firstHalf.numToppings.changes.listen((changeRecord) {
      print("$changeRecord");
    });
  }
  // ...
}
But that is not what Matthew meant. At least I don't think so. Mostly because numToppings is not a real observable. It is a simple integer with no changes stream:
Exception: Class 'int' has no instance getter 'changes'.
NoSuchMethodError: method not found: 'changes'
Receiver: 0
Arguments: []
Instead, perhaps this is something that updates the template:
<link rel="import" href="../../../packages/polymer/polymer.html">
<polymer-element name="x-pizza-toppings">
  <template>
    <p>
      <select id="ingredients" class="form-control" value="{{current}}">
        <option value="">Choose an ingredient...</option>
        <option template repeat="{{ingredient in ingredients}}">
          {{ingredient}}
        </option>
      </select>
      <button id="add" on-click="{{add}}" type="button" class="btn btn-default">
        Add {{name}}
      </button>
      (Currently: {{ numToppings }}, {{ numToppings_old }})
    </p>
  </template>
  <script type="application/dart" src="x_pizza_toppings.dart"></script>
</polymer-element>
Except it doesn't.

The numToppings property is a @ComputedProperty. The numToppings_old is a plain-old, un-annotated getter property. So if the benefit of @ComputedProperty is that it is observable, I would expect only the first number to change when I add a topping. But, when I add a topping, both are immediately changed in the UI:



So I remain confused over the utility of @ComputerProperty. Both it and plain-old getter properties seem to behave the same both in the template and in simple created() life cycle checks (the latter from last night). Am I doing something wrong here?


Day #144

No comments:

Post a Comment