alearg
alearg

Reputation: 685

change in angular.dart change detection method

I have a controller that defines:

I also have a directive that receives the controller's method as a parameter to be able to call it.

After angular.dart v0.9.9. any change in the controller's properties is not detected anymore. Since I use scope only implicitly, through the controller's properties, I am not sure if/how I should use 'scope.context', mentioned in the 'breaking changes' section of angular.dart 0.9.9.

How can I fix this?

[update]

Below is some code:

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    <title>test</title>
  </head>
  <body ng-cloak ng-controller="app-ctrl">
    <div>selections: {{ ctrl.selections }}</div>
    <div class="test-click" whenclicked="ctrl.goRight()">click</div>
    <script type="application/dart" src="/test/web/main.dart"></script>
    <script src="packages/browser/dart.js"></script>
  </body>
</html>

main.dart

library test;
import 'package:angular/angular.dart';
import '../lib/src/app_ctrl.dart';
import '../lib/src/click_dir.dart';
void main() {
  ngBootstrap(module: new TestModule());
}
class TestModule extends Module {
  TestModule() {
    type(AppCtrl);
    type(TestClickDir);
  }
}

app_ctrl.dart

library app;
import 'package:angular/angular.dart';
/** AppCtrl */
@NgController(selector: '[ng-controller=app-ctrl]', publishAs: 'ctrl')
class AppCtrl {
  List selections;
  AppCtrl() {
    selections = ['a','a'];
  }
  void goRight() {
    selections.add('a');
  }
}

click_dir.dart

library clickable;
import 'package:angular/angular.dart';
import 'dart:html';
/** TestClickDir */
@NgDirective(selector: '.test-click', map: const {
  'whenclicked': '&click'
})
class TestClickDir implements NgAttachAware {
  Function click;
  Element self;
  TestClickDir(Element el) {
    self = el;
  }
  void attach() {
    self.onClick.listen((e) => click());
  }
}

Upvotes: 2

Views: 1053

Answers (3)

grohjy
grohjy

Reputation: 2149

I believe this is a bug, because even the watch is not firing, when the length of list changes. If you put a new list into selection (selection = ['a', 'a', 'a']), then the change is updated.

Here is the working example, where selections = selections; makes it work. The _scope.watch is not needed ofcourse, it's here just to give the example of the new syntax (The watch-syntax has changed in version 0.9.9).

EDIT: THIS EXAMPLE IS NOT WORKING. I don't know why it worked when I tested it. I have had to make some mistake earlier, but anyway this is not working. I added the working solution (https://groups.google.com/forum/#!msg/angular-dart/v_t2RUz9lrU/HY7DzAj554sJ)

  AppCtrl(Scope _scope) {
    _scope.watch('selections', (newValue, oldValue) => print("selections: $newValue"), context: this);
    selections = ['a','a'];
  }

  void goRight() {
    selections.add('a');
    selections = selections;
    // or
    selections.add('');
    selections[selections.length-1]='a';
    // following works, the code above don't work
   selections = (selections..add('a')).toList();
  }

Upvotes: 1

alearg
alearg

Reputation: 685

Please have a look here for an explanation of what is going on.

As far as I understand it, a change will never fire because the list doesn't change identity. This code used to work because a re-render, apparently, was always carried out. This is not the case any more for efficiency reasons.

Upvotes: 0

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657018

I guess this is due to optimizations because watching collections is expensive. Could also be a bug though.

I suppose you are using this only for debugging purposes? A slightly different result can be achieved easily with:

{{ ctrl.selections | json }} // prints: ["a","a","a","a","a","a","a"]

just found this works better

{{ ctrl.selections.toString() }} // prints: [a, a, a, a, a, a, a]

Upvotes: 1

Related Questions