Aurelia

Aurelia & Angular 2.0 Code Side by Side - Part 2

Introduction

Aurelia

Aurelia


Aurelia & Angular 2.0 Code Side by Side - Part 2

Posted by Aurelia on .
Featured

Aurelia & Angular 2.0 Code Side by Side - Part 2

Posted by Aurelia on .

Yesterday I showed an example of Angular 2.0 code side-by-side with Aurelia. I showed the "reverse binding" technique for Angular 2.0. Today I'm going to show how the Angular 2.0 Forms Model can be used instead. I'll also show Aurelia next to it, so you can see the difference. Both examples will use the same Contact model.

class Contact {  
  constructor(firstName, lastName){
    this.firstName = firstName;
    this.lastName = lastName;
  }

  get fullName(){
      return `${this.firstName} ${this.lastName}`;
  }
}

Angular 2.0

app.js
import {Component, Template} from 'angular2/angular2';

@Component({selector: 'my-app'})
@Template({url: 'app.html'})
class MyApp {  
  constructor() {
    this.contact = new Contact('John', 'Doe');  
    this.contactForm = new FormControlGroup("form", [
      new FormControl("firstName"),
      new FormControl("lastName")
    ]);
    this.contactForm.readFrom(this.contact);
  }
}

Aurelia

app.js
export class MyApp{  
  constructor(){
    this.contact = new Contact('John', 'Doe');
  }
}

Note: Additional code is needed for Angular 2.0 if ES6/ES5/CoffeeScript is used rather than AtScript since annotations must be "manually transpiled" by the developer.
app.html
<form [control-group]='contactForm'>  
  First Name:
  <input type="text" control="firstName">
  Last Name:
  <input type="text" control="lastName">
  Full Name: {{contact.fullName}}
</form>  
app.html
<form with.bind="contact">  
  First Name:
  <input type="text" value.bind="firstName">
  Last Name:
  <input type="text" value.bind="lastName">
  Full Name: ${fullName}
</form>  

I wanted to let the code stand for itself, as in yesterday's example, but there is something that needs to be clarified about the Angular 2.0 code. It doesn't entirely work. At the bottom of the HTML file you can see where I have {{contact.fullName}}. This will not update in sync with the input controls. The reason is that all of the editable data is stored inside of the FormControl instances and not inside of the Contact model. The data is read in from the model with a call to this.contactForm.readFrom(this.contact); but after that point all state exists external to the model and is not synchronized. After a thorough study of the Angular 2.0 Form Model design document, I could not determine how make this work without:

  1. Duplicating my model's internal logic by hard-coding it into the binding expressions inside the HTML form itself. So, we would have something like this {{contactForm.controls.firstName.value}} {{contactForm.controls.lastName.value}}. However, the design document explicitly calls this out as something that should not be done (because of implications on the binding system).
  2. Merging the Form Model code above, with the code from yesterday and manually calling this.contactForm.writeTo(this.contact); This will result in all the code used in "reverse binding" to be used to trigger calls to update the model. At this point, why use the Form Model?

So, at present, there doesn't seem to be a solution for this in Angular 2.0.

Summary of Angular 2.0 Binding Approaches

If you've read both posts, you can see that there are two different approaches to databinding in Angular 2.0. Each requires using different APIs and binding techniques.

While "reverse binding" appears to be capable of handling any input scenario, it requires authoring lots of code. In fact, what you have to place in your HTML is almost identical to what you would write in JavaScript if there was no binding system involved. This begs the question "why do I need a framework if I have to write the same code anyway?" Also you might be inclined to wonder why you now have to do it in HTML instead of JavaScript.

On the other hand, the Form Model lets you avoid the manual event wirups, but you must abandon your own model. It only works by creating an Angular FormControl model that matches the HTML structure. It's not clear how this approach can handle logic inside any existing model or whether it can allow the creation of more dynamic, data-driven forms. It's also not obvious how a model can be read in that doesn't map nicely to the form structure or written back our correctly. What if the model contains complex logic or its own internal validation?

Summary of Aurelia Binding Approaches

Aurelia uses a single technique in all cases: binding commands. Whenever you see the dot, you know that's a binding. You can use .bind to invoke the default binding mode: one-way binding for everything except input controls, which are bound two-way by default. There's no need to use special models or manually wire events. Code is minimal and clean.

View Comments...