Angular2 Dart - My experience so far

In the last month, I've experimented with many frameworks and multiple languages to find a fitting tool for a new project.

I've played around with KotlinJS, a transpiler that compiles Kotlin to JavaScript, KotlinJS however currently compiles one-to-one to JavaScript, doesn't currently remove dead code, doesn't do any minification (which I easily resolved by adding a Google Clojure Compiler maven plugin to automatically minify everything) and it doesn't do much polyfilling, it's one-to-one. The KotlinJS experience was great, but it's not ready for prime-time yet.

ScalaJS, another transpiler which compiles to JS, my Scala skills are fairly limited and it didn't seem like a great idea learning another JVM language just for the sake of compiling to JS considering the steep learning curve with Scala. (I received a message asking why I went through all the trouble of learning KotlinJS, but not ScalaJS - answer: I already knew Kotlin and picked it up in a day, Scala feels very foreign whereas I picked up Kotlin in a day)

JavaScript with React and Angular2 ... with React, there were so many things I had to manually do to get up and running and the same goes for Angular2, although slightly less on the Angular side since the router and many other useful things just came included, but I still had to manually run my JS via grunt and hope that the minification process doesn't destroy my JS (especially on the Angular side where it's doing dependency injection using a very strange syntax), still had to manually compile my less / sass files or setup build scripts and I had little assurance that my code was type-safe in the critical parts. (I recently discovered the licensing terms for React, if at any point you are competing with facebook, your license is revoked, if at any point two companies are suing each other and both are using React, their license is also revoked - giving facebook the power over when you can and can't use the framework is definitely a no-go for me)

I've decided to give TypeScript a go with Angular2 TS, the experience was somewhat better than JS, but yet again, a lot of manual stuff that had to be done to get up and running, a package.json file, tsconfig.json, typings.json, ... ugh, so much config just to get up and running with a simple hello word and docs that tell you

Scary error messages in red may appear during install. The install typically recovers from these errors and finishes successfully.

Not re-assuring at all, why are they called error messages if you are supposed to ignore them, horrible!!! :-| (somebody on Reddit linking to the article mentioned that the Angular2 CLI fixes the boilerplate problem, I haven't tried that, maybe that makes the Typescript version more bearable)

I've re-visited GWT for a bit and it was as clunky and slow as always and it seems like it's hardly maintained and used by a very small number of people. (I've revisited GWT again last month testing out Angular2-GWT and I was getting much better speeds this time, the syntax is still clunky as hell, the improvements Java8 brought along is not enough to make me switch back to it - give me KotlinGWT, then we're in business)

I've taken TeaVM for a ride, the TeaVM experience was a lot better than KotlinJS and GWT since it had dead code removal, a proper transpiler, but it seemed like a pet-project of someone which made me a bit nervous including it into something that needs to run in the enterprise. (I had a conversation with the creator of TeaVM, he's now on the KotlinJS team)

I finally went full circle back to Dart, I haven't used Angular1 Dart, so had no idea how to get started with Angular2 Dart either. Skimmed through the docs and 5 minutes later I was up and running.

A simple pubspec.yaml file containing the following (note, a single config file):

name: projectname
version: 0.0.1
description: Project Description Goes Here
environment:
  sdk: '>=1.13.0 <2.0.0'
dependencies:
  angular2: 2.0.0-beta.17
  bootjack: any
  bootjack_datepicker: any
  browser: ^0.10.0
  event_bus: any
  http: any
  less_dart: any
  dart_to_js_script_rewriter: ^1.0.1
transformers:
- angular2:
    entry_points: web/main.dart
- dart_to_js_script_rewriter
- less_dart:
    entry_points: [web/styles/main.less]
    build_mode: dart

And voila, I had a less compiler working out of the box, fantastic minification with full Angular2 support and stuff just works.

In my main.dart I simply have the following code to bootstrap everything:

void main() {
    // bootstrap angular2
    bootstrap(AppComponent, [
        ROUTER_PROVIDERS,
        provide(APP_BASE_HREF, useValue: '/'),
        provide(LocationStrategy, useClass: HashLocationStrategy)
    ]);
}

Then I have an AppComponent which takes care of the routing:

@Component(
    selector: 'myapp',
    template: '<router-outlet></router-outlet>',
    directives: const [ROUTER_DIRECTIVES]
)
@RouteConfig(const [
    const Route(path: '/dashboard', component: DashboardPage, name: 'DashboardPage', useAsDefault: true),
    const Route(path: '/home', component: HomePage, name: 'HomePage'),    
])
class AppComponent {

    String name = "Sample App";

}

Since everything is a component, even pages are components, here's my dashboard component

@Component(
    selector: 'dashboard-page',
    templateUrl: '../templates/dashboard-page.html',
    directives: const [Navigation]
)
class DashboardPage {}

Using components are as easy as annotating with @Component and templates can be inlined if they are small enough (like react does):

@Component(
    selector: 'navigation',
    template: '''
        <div class="btn-group br">
            <button type="button" class="btn btn-primary goto-first">
                <span class="glyphicon glyphicon-fast-backward"></span>
            </button>
            <button type="button" class="btn btn-primary goto-prev">
                <span class="glyphicon glyphicon-step-backward"></span>
            </button>
            <button type="button" class="btn btn-primary clear-search">
                <span class="glyphicon glyphicon-refresh"></span>
            </button>
            <button type="button" class="btn btn-primary goto-next">
                <span class="glyphicon glyphicon-step-forward"></span>
            </button>
            <button type="button" class="btn btn-primary goto-last">
                <span class="glyphicon glyphicon-fast-forward"></span>
            </button>
        </div>
    ''')
class Navigation {


}

Want to use components inside other components? Also simple! Let's look at my Item component:

@Component(
    selector: 'item',
    template: '')
class Item implements AfterContentInit {

    @Input() String type = "missing-type";
    @Input() String text = "missing-text";
    @Input() String classes = "";
    @Input() String position = "center";

    @override
    ngAfterContentInit() {

    }

}

Now I can use that Item component inside another component:

<button-search>
                <item type="identifier" text="Identifier"></item>
                <item type="title" text="Title"></item>
                <item type="province" text="Province"></item>
                <item type="city" text="City"></item>
                <item type="suburb" text="Suburb"></item>
                <item type="town" text="Town"></item>
                <item type="address" text="Address"></item>
                <item type="postal" text="Postal"></item>
                <item type="divider"></item>
                <item type="clear" text="Clear Search"></item>
            </button-search>

... and inside my ButtonSearch component I can now get those items to render the SearchButton component.

@Component(
    selector: 'button-search'
    directives: const [NgFor, NgIf, NgClass],
    template: \'''
        <ng-content></ng-content>
        <div class="btn-group search-bar br">
            <div class="input-group">
                <span class="input-group-btn">
                    <a href="#" class="btn btn-primary qr-code" disabled="disabled">
                        <span class="glyphicon glyphicon-qrcode"></span>
                    </a>
                </span>
                <input class="form-control search top focus" type="search" name="search" placeholder="Search">
                <div class="input-group-btn">
                    <button type="button" class="btn btn-primary search top" tabindex="-1">
                        <span class="glyphicon glyphicon-search"></span>
                        Search
                    </button>
                    <button type="button" class="btn btn-primary dropdown-toggle top" data-toggle="dropdown" tabindex="-1">
                        <span class="caret"></span>
                        <span class="sr-only">Toggle Dropdown</span>
                    </button>
                    <ul class="dropdown-menu dropdown-menu-right">
                        <li *ngFor="let item of items" ngClass="{{item.type}}">
                            <a ngClass="{{item.type}}" *ngIf="item.type != 'divider'" href="#">{{item.text}}</a>
                        </li>
                    </ul>
                </div>
            </div>
        </div>\'''
)
class ButtonSearch implements AfterContentInit {

    @ContentChildren(Item) QueryList<Item> items;

    @override
    ngAfterContentInit() {

    }

}

title here

Angular2 Dart - batteries included, Dart polyfilling features that are not completely supported in all modern browsers (so proper cross-browser compatibility out of the box), elegant code and it just works. As far as I'm aware, things are stabilizing now, the router component might get some further rework according to sources close to the team, but otherwise now is a good time to get into Angular2 Dart. The guys on Dart's slack channel also helped me tremendously and a day later, I'm building Angular2 Dart components like a rock star.

Comments (29)

Daniel V's photo

Very good read and welcome to the Dart world! :)

One thing I cannot stress enough about Dart is it's super helpful guys on it's Slack channels.

I've been looking at Angular 2 Dart as well for the past couple months and the experience was very similar to yours - feeling like a Rock Star. An interesting thing I noticed was tiny size of the built JS files of my project. Generally speaking, dart2js can produce large files, especiall if mirroring is used but this does seem to be the case, the compiled application was smaller than the dependencies of the TS version. I was quickly won over!

Show all replies
Jan Vladimir Mostert's photo

Idea Incubator, Full Stack Platform Architect

I hardly have the need for reflection in the frontend, if I do need it, it seems I'll need to go do a refresher in the docs :-)

Ümit Seren's photo

I've re-visited GWT for a bit and it was as clunky and slow as always and it seems like it's hardly maintained and used by a very small number of people.

That's not really correct. GWT 2.8 supports Java8 syntax that means you can leverage lambdas which make async code even more concise than the ES6 version. Furthermore SuperDevMode is really very fast. It's also not true that it is only used by few people and not maintained (check the github logs: https://github.com/gwtproject/gwt/commits/master, most commits are from Google Members but also contribution from the community). Also GWT is used for Google Inbox, Google Spreadsheet and used to write business code once in java and use it in iOS, Android and the Web. GWT 2.8 supports a brand new JsInterop (zero cost abstraction) that currently even easier to use than the Dart's JsInterop. Google is also working on GWT 3.0 which will be a pure Java to ES6 transpiler and reduce the compiler complexity a lot. There is also work done on leveraging Typescripts type definitions for various JS libraries to automatically create JsInterop Java interfaces to be used from GWT.

Show all replies
Jan Vladimir Mostert's photo

Idea Incubator, Full Stack Platform Architect

Also based on Google Trends, GWT has seen a decline in interest since 2011, in 2013 AngularJS just went inferno. https://www.google.com/trends/explore#q=%2Fm%2F0d6jq1%2C%20GWT%2C%20%2Fm%2F012l1vxv%2C%20%2Fm%2F0j45p7w&cmpt=q&tz=Etc%2FGMT-2

Ted Sander's photo

That has been our experience with Angular2.dart as well. Welcome! We are excited for it to get even better!

Jan Vladimir Mostert's photo

Idea Incubator, Full Stack Platform Architect

Looking forward :-D

Zoltan Debre's photo

If you are looking for a corporate ready, serious framework, I would recommend Ember.js also. With ES6, and with ember-cli, it is a real a game changer and solid as rock. And it is already a proven solution for serious frontend apps.

Show all replies
Jan Vladimir Mostert's photo

Idea Incubator, Full Stack Platform Architect

querySelector is a good example, it's only partially supported in some browsers (partial support in IE8 and buggy on IOS) - if I use it in JavaScript, chances are that it might work in some browsers and might break in another browser - I now need to go check which JS APIs I can use and can't use based on the browsers I want to support (painful)

Use querySelector in Dart and it'll work across all browsers that Dart says is supported, if not you file a bug and Google fixes it.

Vlad's photo

Hi, great article!

How would you recommend to approach internationalisation in an angular 2 dart application? I'm building a web application that needs to support multiple languages.

Show all replies
Daniel V's photo

Runnin around in front-end code and having a blast!

Hello Vlad, another approach would be not to localize your website on code level but rather translate it with a translation proxy solution. Easyling is a very well known one - guess what language was chosen for it's front-end ;)

Very little to no extra coding is required to get a translated website up and running with it. Sign up for a demo, they'd be happy to show you around!

Arnaud Garcia's photo

Same Conclusion ! I would like to know what do you think for backend ? still using dart ?

Show all replies
Jan Vladimir Mostert's photo

Idea Incubator, Full Stack Platform Architect

I'm not using Dart in the backend - main reason is that it doesn't cover all my needs at the moment. Although you can have a look at Dart's Redstone micro framework which should be sufficient for most people. I'm currently using Kotlin + Spring since the existing infrastructure is all Java8 + Spring based. Frontend I've been churning out 1000s of lines of Dart code in the last two weeks all Angular2, nearly halfway finished with a project that I just started.

Marcin Sz.'s photo

I agree with @timeu that GWT's SuperDevMode is really very fast. Please compile and deploy demo Angular2 project in Java8 (GWT) from here: http://lteconsulting.fr/angular2boot/ .

SuperDevMode is something what Dart doesn't have. At least recently. And all the conclusions come from the interview with Joshy Joseph (the primary technical lead for AdWords UI). Here is my Dart vs GWT comparison and for me Dart is still not matured enough. http://deploythoughts.blogspot.com/2016/04/the-new-adwords-ui-uses-dart-what-does.html

It's like reinvent the wheel.

Now they want to improve Dart and add things as following:

  • Dart Strong Mode when GWT has stronger type checking out of the box,
  • fast edit refresh when GWT has great SuperDevMode,
  • and also would like to have better js interop what GWT has.

Some of the things mentioned above could have been added recently, so this is the status from April.

So I would rather think that Dart is slow and my choice if about Angular2 would be TypeScript, not Dart. But I can choose also Java.

So I don't agree with your conclusions regarding GWT. It works well out of the box. Important thing is to use the latest version 2.8. Btw. today has been released 2.8RC1 and the final release is planned within 2 weeks. It's actively developed and new features are on the way. GWT 3 (J2CL) is now closer

I agree with @timeu and I'm not going to repeat his words.

If about Kotlin, yes it's interesting. But when I considered KotlinJS, the problem was with libs, frameworks and tooling. Another option would be ScalaJS where you can find more ready to use libs. Maybe we need more time for Kotlin. If about GWT the landscape is really huge and Java 8 is powerful enough. What more we have Javaslang and you can find support for GWT which is being developed: https://github.com/javaslang/javaslang/tree/master/javaslang-gwt .

So complaining on GWT is rather about the past. There were the bad old days, but now it's being actively developed.

Jan Vladimir Mostert's photo

Idea Incubator, Full Stack Platform Architect

I ran the angular gwt example using mvn gwt:run-codeserver, first thing I noticed: @Components needs to be annotated with @JsType as well, properties needs to be annotated with @JsProperty, constructurs needs to be annotated with @JsConstructor, methods with @JsMethod, ... besides getters and seters, that's a lot of extra boilerplate don't you think? Apparantly my browser is too old for Angular GWT to run (I'm busy on a CentOS box), so I'll have to try it some other time on my MacBook, the annotation boilerplate already put me off though.

Dart Strong Mode when GWT has stronger type checking out of the box,

Dart already has Strong Mode, it's just being improved. The benefit of Dart here over GWT is that types are optional, I don't have to be bogged down by writing types everywhere. The benefit being that I can move a lot faster, get things done and then have types added later on if I really need to. This is one benefit of Kotlin as well, inferred types, in Java you still need to write out the types everywhere.

Tell me which one is less code to write:

Java8:

String value = Optional.ofNullable(somemethodThatCanReturnNull()).orElse("value");

Kotlin:

var value = somemethodThatCanReturnNull() ?: "value"

or if you really want to, but the above one infers the type, so this is not needed:

var value:String = somemethodThatCanReturnNull() ?: "value"

Dart:

var value = somemethodThatCanReturnNull() ?? "value";

or

String value = somemethodThatCanReturnNull() ?? "value";

And I can cite many more examples where Kotlin and Dart are simply less code to write to get the same thing working. For UI development, this is crucial. Most of the UI doesn't even require strong typing, server-side I fully agree with strong typing, but does it really make sense in the UI when most of your inputs will probably be Strings ?

fast edit refresh when GWT has great SuperDevMode,

Dart has a special Dartium browser which gives me exactly this (instant refreshes, although only on chrome) as well as Observatory which gives me deep insights into memory consumption, I can track object creation to make sure I don't have leaks, set breakpoints in the browser, etc. Development is done in Dartium, only then I test in IE, Firefox, Safari, etc, but even when I do test it in browsers outside Dartium, it's generally fast enough after the pub server warmed up. So "super-dev mode", although a useful feature, it's not something that's missed by myself; I've generally tested other browsers on the QA server already compiled to JS and had no issues with the generated JS before.

and also would like to have better js interop what GWT has.

In the places where I've experimented with JS-interop, it was working just fine in Dart, JS-interop is generally not something I use.

From your blog:

Ongoing work on Flutter for Dart; if about GWT we can use already Cordova, Phonegap, Appcelerator Titanium (via Titanium4J), ...

Dart is also available with Cordova and Phonegap, you also get DartGap which wraps Cordova and then there's Flutter to look forward to which will blow Cordova and Phonegap out of the water when you all of a sudden have native-like Andriod / iOS support via Dart.

Get me KotlinGWT with everything JavaGWT currently has and you have my attention (the direction Kotlin is going with WASM support, I'd probably stick to Dart or use Kotlin when WASM becomes reliable), Optional Types and Inferred Types are what I'm after in UI development (and on the server as well since I switched to Kotlin), Strongly Typed and boilerplate slows me down.

If you're preferring Angular2 TypeScript over Angular2 Dart, chances are you haven't used Dart yourself.

nn's photo

How things working out with AngularDart for you? I am in same situation as you OP but it is 2017.

Show all replies
Jan Vladimir Mostert's photo

Idea Incubator, Full Stack Platform Architect

Currently using Foundation as a base, then everything else is custom-built. Haven't had time to go deep into the material design components that you get with Dart, Foundation seems good enough for now, it's very minimalistic and doesn't get in your way when you want to build custom things.

For my Kotlin REST API, I use VertX with my own library of extension methods on top of it to make it easier to use

The dart generator is currently semi-proprietary, but I can explain how it is done so you can easily build your own one. It's mostly using reflection to traverse through a Kotlin class and then simply spit out strings in a .dart file. If the Kotlin model is updated, the Dart model gets updated as well when you compile the Kotlin code.

generateDartClass(CompanyCreate::class)

fun generateDartClass(clazz: KClass<*>): List<String> {
    clazz.declaredMemberProperties.forEach { property ->
        when (property.returnType.toString()) {
           "kotlin.String" -> { 
               // generate Dart String declaration here
           }
           "kotlin.Int" -> {
              // generate Dart Int declaration here
           }
           ...
        }
    }
}

Now when you serialize to and from JSON, both sides have proper models you can work against which should give you some nice autocomplete assistance.