Saturday, September 27, 2014

Binding Variables Between Angular and Polymer (latest Dart packages)

Last night I was able to get Polymer.dart and Angular.dart working together again. But I don't have them working together yet.

I have my <x-pizza> Polymer element working within an Angular partial:

But I do not have the two communicating. When I originally wrote the Angular & Polymer chapter in Patterns in Polymer, I was able to reflect changes from the Polymer element back into the Angular application through the use of angular_node_bind. That was a long time ago, let's see if it still works.

Before diving into it, I need to get Angular setup properly. I had remove the variable binding element last night from my partial:
<h3>Oooh! Let's make beautiful pizza together</h3>
<pre>{{ pizzaState }}</pre>
  <x-pizza pizzastate="[[ pizzaState ]]"></x-pizza>
With that <pre> element bound to the pizzaState property, I get errors like:
No getter for 'pizzaState'.

#0      StaticClosureMap.lookupGetter (package:angular/core/parser/static_closure_map.dart:15:25)
#1      DynamicParserBackend.newAccessScope (package:angular/core/parser/dynamic_parser.dart:112:38)
#2      DynamicParserImpl.parseAccessOrCallScope (package:angular/core/parser/dynamic_parser_impl.dart:257:67)
#3      DynamicParserImpl.parsePrimary (package:angular/core/parser/dynamic_parser_impl.dart:239:36)
#4      DynamicParserImpl.parseAccessOrCallMember (package:angular/core/parser/dynamic_parser_impl.dart:193:30)
This turns out to be caused by omitting the partial from the list of Angular files in my application's pubspec.yaml:
name: angular_example
  angular: any
  polymer: any
  angular_node_bind: any
  args: '>=0.10.0 <0.12.0'
  code_transformers: '>=0.1.4+2 <0.3.0'
  html5lib: '>=0.10.0 <0.13.0'
  unittest: any
- angular:
      - web/partials/custom.html
- polymer:
    - web/index.html
    - test/index.html
With this “custom” pizza partial listed, my error are fixed. But the bound attribute is still not reflected back into the Angular application.

To make that work, I need no changes to my <x-pizza> backing class definition:
class XPizza extends PolymerElement {
  // ...
  @published String pizzaState;
  // ...
I find that interesting because it does not appear to need the @PublishedProperty(reflect: true) annotation that I would have expected. The only change I that I need is using the angular_node_bind directive in my app:
// ...
import 'package:angular_node_bind/angular_node_bind.dart';
// ...
main() {

    var app = new PizzaStoreApp()
      ..bind(NgRoutingUsePushState, toValue: new NgRoutingUsePushState.value(false))
      ..bind(RouteInitializerFn, toValue: storeRouteInitializer);

Happily, that directive still works just fine. I continue to bind the Angular pizzaState variable to the Polymer element's pizzastate attribute in the template:
<pre>{{ pizzaState }}</pre>
  <x-pizza pizzastate="[[ pizzaState ]]"></x-pizza>
With the double-square brackets serving as angular_node_bind's way of watching properties. And it works:

When the Polymer updates its pizzastate, Angular sees the change and updates its pizzaState variable, which is reflected in the <pre> element from the Angular template. Nice!

The WARNING on the page is Polymer's way of telling me in development mode that it was unable to interpret the <ng-view> element from Angular. I can certainly live with that since Polymer was not suppose to interpret it anyway. I think I am nearly satisfied with the solution to the point that I can again include it in the book.

Day #196


  1. The newest version of angular-dart (0.14.0) should support binding with polymer-dart. See:

    1. Ooh! I had completely forgotten about that. Will give it a whirl. Thanks!