Wednesday, October 16, 2013

Getting Started with Angular.Dart


I think I lost some hipster cred by missing the AngularJS boat. Also, I lost hipster cred by using the phrase “hipster cred,” but let's face it, I never really had any hipster cred to lose so I'm good. Still, Angular intrigues me, so I would like to explore it a bit more. To get the most enjoyment from the effort, I will try the Dart verison of Angular because Dart makes everything happier!

I start a new Dart web application in a new application directory with a new pubspec.yaml file:
name: angualar_test
dependencies:
  angular: any
dev_dependencies:
  unittest: any
Next, I pub get the angular package and all of its current dependencies:
➜  angular-test git:(master) ✗ pub install
Resolving dependencies.......................
Downloading angular 0.0.2 from hosted...
Downloading unittest 0.8.2 from hosted...
Downloading perf_api 0.0.8 from hosted...
Downloading di 0.0.24 from hosted...
Downloading html5lib 0.8.2 from hosted...
Downloading browser 0.8.2 from hosted...
Downloading analyzer_experimental 0.8.2 from hosted...
Downloading intl 0.8.2 from hosted...
Downloading meta 0.8.2 from hosted...
Downloading stack_trace 0.8.2 from hosted...
Downloading utf 0.8.2 from hosted...
Downloading source_maps 0.8.2 from hosted...
Downloading path 0.8.2 from hosted...
Downloading args 0.8.2 from hosted...
Downloading logging 0.8.2 from hosted...
Downloading unmodifiable_collection 0.8.2 from hosted...
Got dependencies!
How cool is Dart that functionality can be easily broken out into separate packages like that and easily installed for client-side use?

Anyhow, my goals for tonight are modest: get the “Basics” app working. The HTML for the JavaScript version is:
<!doctype html>
<html ng-app>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
  </head>
  <body>
    <div>
      <label>Name:</label>
      <input type="text" ng-model="yourName" placeholder="Enter a name here">
      <hr>
      <h1>Hello {{yourName}}!</h1>
    </div>
  </body>
</html>
The <script> tag will have to change to the Dart equivalent. The Angular Dart package does not contain any JavaScript code, so the VM initialization will have to come from the browser package. But what should the main() entry point be for the Angular code?

After rooting through the package a bit—and finding nothing—I finally notice that the source code features an example that does just what I am trying to do. It even has the main() entry point that I need. So the <head> section of my HTML becomes:
  <head>
    <script type="application/dart" src="main.dart"></script>
    <script src="packages/browser/dart.js"></script>
  </head>
Leaving main.dart to bootstrap the Angular application:
import 'package:angular/angular.dart';
main() {
  bootstrapAngular([new AngularModule()]);
}
Following Dart Pub conventions, I place index.html and main.dart into the web sub-directory:
➜  angular-test git:(master) ✗ tree -I packages
.
+-- pubspec.lock
+-- pubspec.yaml
+-- web
    +-- index.html
    +-- main.dart

1 directory, 4 files
With that, I am ready to quickly fire up pub serve (well not too quickly since it now runs dart2js first) to try things out:
➜  angular-test git:(master) ✗ pub serve
Serving angualar_test on http://localhost:8080
And it just works!



That was pretty darn easy. Compared to the JavaScript version, it is obviously a minor inconvenience to have to create the main.dart file just to bootstrap the application. Then again, how often are people going to want to create a ridiculously easy sample application like this? The power of Angular is in backing code for binding, writing directives and the like. I will get started on those tomorrow.


Day #906

2 comments:

  1. Ugh, I will not get used to the "main()" thing in Dart ever. Too much C

    ReplyDelete
    Replies
    1. There are ways around it. Polymer.dart doesn't use a main():

      * https://github.com/eee-c/ice-code-editor/blob/polymer/web/polymer.html
      * https://github.com/eee-c/ice-code-editor/blob/polymer/web/polymer.dart

      Regardless, I really like it. I want to know that static classes and similar are not going to be affected by other code that may happen to be running on my page. The main() creates an isolate in which you're guaranteed that only code from that main() can affect it.

      That's part of the appeal of requirejs and the like in the JavaScript world. Learn to love main() :D

      Delete