Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Ease Angular adoption: support a *simple* CDA based on equality (in addition to the new CDA) #705

@chalin

Description

@chalin

Executive summary

While I used to be able to write a single ng-repeat collection expression like names.split(',') in my HTML file, it seems that under Angular's new Change Detection Algorithm (CDA) I have to replace that by a custom 10-line-or-so @NgController that implements caching. This will not aid AngularDart adoption. I admired Angular because it allowed me to focus on web app design rather than writing boilerplate code, but this seems to be a step backwards. Details are given below.

A solution I propose is to have Angular support at least two CDAs: one which is the simplest possible to use (automatic family sedan version) and then the new CDA (turbocharged formula 1 version, ... or think "Jeep without doors or safety belts") targeted for experts ;).


DETAILS

I believe that a selling point of Dart is that it gives its users choices. Consider types as one example: to quote Gilad Bracha in his concluding remarks to Optional Types in Dart:

If you hate types, you need not use them at all. ... If you love types, you may use them everywhere

Since January I have been teaching a graduate course in Dart and AngularDart. Up until the the introduction of the new Change Detection Algorithm (CDA) of v0.9.9, I was able to develop considerable lecture material supported by examples without any surprises. In particular, it was pleasant to see that simple web apps were simple to write.

I understand that the new CDA is highly optimized so that it can support:

  • 20,000 field checks and
  • 300,000 array element checks

per millisecond [1], but this comes at the cost of rendering many simple intuitively-correct web apps either completely invalid or requiring considerable rewrite. I give an example of each case below.

Example: Simple app that is now invalid

I have a suite of elementary examples illustrating basic functionality of AngularDart without the use of custom controllers. Here is one example:

Team member names (comma separated):<input type="text" ng-model="names">
<ul ng-if="names != null">
  <li ng-repeat="name in names.split(',')">{{name}}</li>
</ul>

This runs nicely under 0.9.8:

image

Now under the new CDA we get the following error:

Observer reaction functions should not change model. 
These watch changes were detected: names.split(","): [Alice,  Bob] <= [Alice,  Bob]

The message is complaining that the list [Alice, Bob] isn't the same as the list [Alice, Bob]. This will confuse most newcomers. What is happening is that the new CDA doesn't like that the expression names.split(',') yields a new list instance every time it is evaluated --- despite the fact that it generates the same list value every time.

Under the new CDA, I see no solution to this other than writing a customer controller. Let's try that next.

Example: Restrictions on custom controllers

A first try at writing a custom controller to solve the problem illustrated above might be:

@NgController(selector: '[team-name-controller]', publishAs: 'ctrl')
class TeamNameController {
  String names;
  List<String> get nameList => names == null ? [] : names.split(',');
}

with corresponding changes to the HTML

Team member names (comma separated):<br>
<input type="text" ng-model="ctrl.names">
<ul ng-if="ctrl.names != null">
  <li ng-repeat="name in ctrl.nameList">{{name}}</li>
</ul>

But this yields the same warning we got before: Observer reaction functions should not change model.

I raised this issue earlier (#641), in which I gave a different example of a controller that generated a list of int values:

List get list => new List.generate(3, (i) => i)

and the response was that under the new CDA I need write something like

class MyController {
  List list;

  MyController(MyService service) {
    service.onDataChanged.listen((_) {
      _updateData();
    });
  }

  _updateData() {
    list = new List.generate(3, (i) => i);
  }
}

Is this really the simplest possible solution under the new CDA? While I admired Angular because it allowed one to focus on web app design rather than writing boilerplate code, this seems to be a step backwards. This will not help the adoption of AngularDart.

A Possible Solution

The main problem, IMHO, is the belief that "one size fits all" when it comes to CDA. I think that there should be at least two CDAs:

  • one CDA which is the simplest possible to use and is based on element equality, including special treatment for collections;
  • the new CDA for diehard web app writers needing to support the watch and update of tens of thousands of elements

with the former being the default.

[1] Change Detection. Status: Draft. Accessed March 11, 2014. Author: Misko Hevery

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions