1

I have an app using @NgController and the working use case where an UI action triggers a change in the model, which immediately get reflected in the view. The model consists of a list of objects.

What is not working is when the triggered action is starting some asynchron process which eventually modifies the model (adds new elements in the list). The view gets no update.

I guess this works as designed and I am missing something. What pattern should I use in this case?


UPDATE: Here the minimal code snippet showing the problem:

<html ng-app>
  <head>
    <meta charset="utf-8">
    <title>Angular bug test</title>
    <link rel="stylesheet" href="angular_bug_test.css">
    <script src="http://lounge-server.jit.su/socket.io/socket.io.js"></script>
  </head>
  <body test>
    <h1>Angular bug test</h1>

    <p>The number of element in the list is {{controller.list.length}}</p>
    <input ng-click="controller.addElementSync()" type="button" value="Add Sync"></input>
    <input ng-click="controller.addElementAsync()" type="button" value="Add Async"></input>
    <input ng-click="controller.addElementJsAsync()" type="button" value="Add JS Async"></input>
    <ul>
      <li ng-repeat="element in controller.list">{{element}}</li>
    </ul>

    <script type="application/dart" src="angular_bug_test.dart"></script>
    <script src="packages/browser/dart.js"></script>
  </body>
</html>

and the corresponding dart code:

@NgController(selector: '[test]', publishAs: 'controller')
class TestController {

  List<String> list = new List<String>();

  void addElementSync() {
    list.add("${list.length}. element");
  }

  void addElementAsync() {
    new Timer(new Duration(seconds: 1), () => list.add("${list.length}. element"));
  }

  void addElementJsAsync() {
    context['io']
      .callMethod('connect', ['http://lounge-server.jit.su:80/'])
      .callMethod('on', ['connect', _onConnect]);
  }

  void _onConnect() {
    Logger.root.fine('connected');
    list.add("${list.length}. connected");
    Logger.root.fine('list.length = ${list.length}');
  }

}

When triggering the Add JS Async button the console shows the following:

FINE : connected
FINE : list.length = 6

Unfortunately, neither the ng-repeat nor the {{controller.list.length}} gets updated.


UPDATE: The following workaround fix this problem in JS interop (kudos to James)


  NgZone _zone;

  TestController(NgZone this._zone);


  void addElementJsAsync2() {
    context['io']
      .callMethod('connect', ['http://lounge-server.jit.su:80/'])
      .callMethod('on', ['connect', _zone.run(_onConnect)]);
  }

UPDATE: The bug is still present in 0.11.0 and NgZone has been renamed VmTurnZone

4

1 回答 1

1

您所描述的内容应该是开箱即用的。唯一棘手的部分是处理列表:为了检测列表中的变化,必须使用自定义指令Scope.$watchCollection来监视集合。普通手表和属性图会错过列表中的更改。

处理列表(例如 )的内置指令ng-repeat已经使用$watchCollection.

于 2014-01-31T04:20:53.207 回答