-
Notifications
You must be signed in to change notification settings - Fork 248
Ease Angular adoption: support a *simple* CDA based on equality (in addition to the new CDA) #705
Description
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:
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