Thanks to a tip from
James Hurford, I have a far better approach to working with the “wildly” incompatible
Polymer.dart and
Angular.dart libraries. Instead of hacking on a forked version of Angular.dart, as I did last night, I instead use
Dart Pub's
dependency_overrides
option.
I am simply not going to start hacking on Angular.dart to get Polymer elements working inside an Angular.dart application—especially not as a solution for
Patterns in Polymer. Overriding the minimal dependencies found from last night gives me the best chance of working with the most recent Polymer and Angular libraries to see if it is as all possible.
So I add those dependencies to my project's
pubspec.yaml
:
name: angular_example
dependencies:
angular: any
polymer: any
angular_node_bind: any
dependency_overrides:
args: '>=0.10.0 <0.12.0'
code_transformers: '>=0.1.4+2 <0.3.0'
html5lib: '>=0.10.0 <0.13.0'
dev_dependencies:
unittest: any
transformers:
- polymer:
entry_points:
- web/index.html
- test/index.html
I delete my
pubspec.lock
to be absolutely sure that I am getting a fresh run at this (a
pub upgrade
should do the same thing). Now when I run
pub get
, I find:
$ pub install
...
+ angular 0.14.0
...
+ polymer 0.15.0
...
Warning: You are using these overridden dependencies:
! args 0.11.0+1 (0.12.0+2 available)
! code_transformers 0.2.3+1
! html5lib 0.12.0
For reference, Angular.dart would otherwise restrict those three overridden dependencies as:
args: '>=0.10.0 <0.11.0'
code_transformers: '>=0.1.4+2 <0.2.0'
html5lib: '>=0.10.0 <0.11.0'
OK, I have the
Dart versions of Polymer and Angular installed in the same application. Now what?
Well, for tonight, I would be satisfied with a working version of the old Angular pizza building application that uses a custom Polymer element. This worked when it went into
Patterns in Polymer. Hopefully it can live again.
I modify the Polymer setup as I know that version 0.15 likes it and retain the Angular tags and attributes:
<!doctype html>
<html ng-app lang="en">
<head>
<script src="packages/web_components/platform.js"></script>
<link rel="import" href="packages/angular_example/elements/x-pizza.html">
<script type="application/dart" src="main.dart"></script>
</head>
<body>
<div class="container">
<h1>Ye Olde Dart Pizza Shoppe</h1>
<ng-view></ng-view>
</div>
</body>
</html>
Aside from the
ng-app
Angular attribute and the
<ng-view>
Angular tag, there is one other difference between this and a pure Polymer application: there is no export of
package:polymer/init.dart
to initialize Polymer. Instead that is done inside
main.dart
, which also initialized Angular.
At least it used to initialize Angular. Now it just generates errors in the
Dartium console:
Exception: No top-level method 'ngBootstrap' declared.
NoSuchMethodError: method not found: 'ngBootstrap'
Receiver: top-level
Arguments: [...]
No biggie. It seems that the Angular bootstrap process has changed. For now, I leave the initialization inside Polymer's
run()
:
main() {
initPolymer().run((){
applicationFactory()
.addModule(new PizzaStoreApp())
.run();
});
}
No doubt other stuff has changed, but I start with the old constructor for
PizzaStoreApp
and will work my way from there. What I find next is:
Exception: Module.DEFAULT_REFLECTOR not initialized for dependency injection.http://goo.gl/XFXx9G
This appears to be due to the lack of the Angular transformer in my pubspec.yaml. Despite what the documentation says, it would appear that this does more than aid building JavaScript. I add the Angular transformer:
name: angular_example
dependencies:
angular: any
polymer: any
angular_node_bind: any
dependency_overrides:
args: '>=0.10.0 <0.12.0'
code_transformers: '>=0.1.4+2 <0.3.0'
html5lib: '>=0.10.0 <0.13.0'
dev_dependencies:
unittest: any
transformers:
- angular
- polymer:
entry_points:
- web/index.html
- test/index.html
After a
pub serve
restart, there is much work to perform to update the Angular portion of my application to 0.14. But I eventually get it.
The application is intentionally “complex-ish” to ensure that I am not just getting by with a trivial example. Mostly this involves routing.
The
main.dart
file for my Angular & Polymer application starts with the usual imports for both libraries:
import 'package:polymer/polymer.dart';
import 'package:angular/angular.dart';
import 'package:angular/application_factory.dart';
import 'package:angular/routing/module.dart';
There used to be much initialization inside the main application module. Now it is just:
class PizzaStoreApp extends Module {
PizzaStoreApp() {
// Stuff used to happen here, now routing and binding happens later...
}
}
I am unsure if I even need this anymore, but I will answer than another day.
The routing uses two partials, defined as:
void storeRouteInitializer(Router router, RouteViewFactory views) {
views.configure({
'start': ngRoute(
defaultRoute: true,
view: 'partials/home.html'
),
'custom-pizza': ngRoute(
path: '/pizza/custom',
view: 'partials/custom.html'
)
});
}
That is relatively self-explanatory. I have two routes: the default route and the custom pizza route. Both use partial templates at the specified locations.
Finally, the Polymer and Angular initialization looks like:
main() {
initPolymer().run((){
var app = new PizzaStoreApp()
..bind(NgRoutingUsePushState, toValue: new NgRoutingUsePushState.value(false))
..bind(RouteInitializerFn, toValue: storeRouteInitializer);
applicationFactory()
.addModule(app)
.run();
});
}
It took a little time to figure out where the
bind()
calls go and what gets supplied to
addModule()
, but it mostly makes sense. What took me quite a while to figure out was how to disable push state. I really hate push state—especially for developing / reloading single page applications. But eventually I figured out how to bind the
false
value of
NgRouteingUsePushState
. There may be a cleaner way to accomplish this, but I am not going to worry about that now.
Because I have an Angular.dart 0.14 + Polymer.dart 0.15 application working:
Well, not quite working. I still need to double bind variables in Angular to Polymer attributes. But I am thrilled to have gotten this far tonight.
Day #195
‹prev | My Chain | next›