Two-way data binding with Web UI custom elements and models

This could very well be my last Web UI post! The Dart team announced they started on polymer.dart, a port of the Polymer project to Dart. Polymer.dart is the next evolution of Web UI. Luckily, the concepts are mostly the same and the syntax is mostly the same, because Web UI is also an implementation of the Web Components.

So why am I still writing about Web UI? Lots of people have asked about two-way data binding between a component and a model, so I wanted to have a record of this functionality. Also, what's described below isn't too different than how polymer.dart works (and we'll cover it in a future post).

I look forward to the glorious new world of coordinated polyfills and new custom elements. Go go polymer.dart and the Polymer project!

Intro

The Dart class that backs a custom element can itself also take part in two-way data binding. This post explores how to bind a model object to a web component property. If a model's field changes, the custom element's property changes. If the custom element's property changes, the model's field changes.

(Note: the same technique, with different syntax, should work in polymer.dart as well.)

The demo app contains:

A model for a Switch

A custom element for a Toggle

The goal

When the switch is flipped, we want to flip the toggle. When the toggle is flipped, we want to flip the switch. Both Switch and Toggle don't know about each other. Let's connect them!

Defining the Switch model

The Switch class is a standard business model, and it's marked as @observable.

Press the Toggle button (the custom component) and it runs toggle() which flips the ToggleComponent's internal state field. Because state is bound to lightSwitch.flipped, the switch is also flipped. Pretty cool!

Summary

You can bind a component's property to a model's field. This works today with Web UI's bind-foo attribute, and should work with polymer.dart's foo="{{model.field}}" attribute.

Meanwhile, Web UI is being phased out in favor of polymer.dart. Both libraries have the same goal: provide excellent implementations of modern and emerging web specifications and to help developers build amazing modular and beautiful web apps!

In which I port a snazzy little JavaScript audio web app to Dart, discover a bug, and high-five type annotations. Here's what I learned.

[As it says in the header of this blog, I'm a seasoned Dart developer. However, I certainly don't write Dart every day (I wish!). Don't interpret this post as "Hi, I'm new to Dart". Instead, interpret this post as "I'm applying what I've been documenting."]

This post analyzes two versions of the same app, both the original (JavaScript) version and the Dart version. The original version is a proxy for any small JavaScript app, there's nothing particularly special about the original version, which is why it made for a good example.

Warning: We expect the Dart libraries to undergo potentially sweeping changes before Dart goes to alpha. This document is relevant as of 2011-12-22.

Intro

Dart is a "batteries included" effort to help app developers build modern web apps. An important "battery" is the bundled core Dart libraries, providing common and rich functionality. Dart is building a solution for large, complex web apps, and providing well tested, integrated, and common libraries is key to helping a web app developer be more productive out of the box.

The Collection libraries are a crucial set of APIs that Dart developers get for free. Much more than simple arrays and maps, the Collection library includes standard ways to filter, iterate, inspect, compose, and sort your data. This post specifically looks at List<E>, Dart's ordered, indexable collection of objects.