Привязка данных к карте в Angular Dart

Я пытаюсь реализовать функциональность для проверки нескольких элементов в списке флажков. Я использую карту для хранения данных и ее выбранного/невыделенного состояния.

List<String> fruits = [
  {'fruit': 'apple', 'selected': true},
  {'fruit': 'banana', 'selected': true},
  {'fruit': 'kiwi', 'selected': false}
];

Флажки изначально отображаются с правильно отображаемым статусом отмечен/не отмечен, но когда я переключаю статус отмеченного флажка, карта fruits не обновляется. Как здесь правильно создать двустороннюю привязку?

Вот мой файл .dart:

import 'package:angular/angular.dart';

@NgDirective(
  selector: '[my-controller]',
  publishAs: 'ctrl'
)
class MyController {
  List<String> fruits = [
    {'fruit': 'apple', 'selected': true},
    {'fruit': 'banana', 'selected': true},
    {'fruit': 'kiwi', 'selected': false}
  ];
}

main() {
  ngBootstrap(module: new Module()..type(MyController));
}

А вот разметка вида:

<!DOCTYPE html>
<html ng-app>
  <body>
    <div my-controller>            
      <ul>
        <li ng-repeat="item in ctrl.fruits">
          {{item['fruit']}}
          <input type="checkbox" ng-model="item['selected']" />
        </li>
      </ul>
    </div>

    <!-- THIS DOES NOT UPDATE WHEN THE CHECKBOXES ARE TOGGLED -->
    {{ctrl.fruits}}

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

person Shailen Tuli    schedule 07.01.2014    source источник
comment
Некоторые дополнительные данные: если я изменю разметку в <li> на {{item['fruit']}}-{{item['selected']}}, переключение флажков явно изменит поле selected. А вот карта {{ctrl.fruits}} в целом вроде не обновляется.   -  person Shailen Tuli    schedule 07.01.2014
comment
Я добавил периодический таймер в конструктор, который печатает карту. Значение «выбрано» обновляется на карте при изменении флажка. Только {{ctrl.fruits}} не обновляется.   -  person Günter Zöchbauer    schedule 07.01.2014


Ответы (3)


Причина, по которой он не обновляется, заключается в том, что ctrl.fruits отслеживается по ссылке. Поскольку ссылка на список fruits никогда не меняется, привязка также никогда не меняется.

Вот простое решение:

{{ctrl.fruits | json}}

Пропуская его через фильтр, он заставляет объект быть JSONified в каждом дайджесте.

К сожалению, нет простого способа глубокого наблюдения за объектом, поскольку вычислительная сложность потенциально неограниченна.

person Misko Hevery    schedule 07.01.2014

Редактировать 2 Я нашел 2 полезных решения ИМХО

1

{{ctrl.fruits.toString()}}

2

<div ng-repeat="item in ctrl.fruits">{{item['fruit']}} - {{item['selected']}}

Изменить

небольшое улучшение, но все же уродливый обходной путь

  void update() {
    var tmp = fruits;
    fruits = null;
    Timer.run(() => fruits = tmp);
  }
<input type="checkbox" ng-model="item['selected']" ng-click="ctrl.update()"/>

Сначала я добавил таймер, который периодически вызывает

new Timer.periodic(new Duration(milliseconds: 2000), (t) => print(fruits = new List.from(fruits)));

при этом вывод обновляется.
Я еще не понял, как обойтись без таймера.
Я думаю, что распознаются только изменения члена фруктов, но не изменения элемента внутри списка.
Может иметь отношение к Как просмотреть элементы коллекции AngularDart?

person Günter Zöchbauer    schedule 07.01.2014

Я предполагаю, что нужно попробовать $watch... Я не знаком с дротиками, но ваша проблема звучит точно так же, как ваш объект не глубоко просматривается. Без глубоких часов angular видит fruits как массив с 3 объектами и не будет смотреть дальше этого. С глубоким просмотром он увидит массив с 3 объектами, а ТАКЖЕ свойства этих объектов, и он должен обновляться при их изменении.

ИЗМЕНИТЬ

Вот JSFiddle, написанный на чистом JS... он работает так, как и следовало ожидать, с этим JS

function TodoCtrl($scope) {
  $scope.fruits = [
  {'fruit': 'apple', 'selected': true},
  {'fruit': 'banana', 'selected': true},
  {'fruit': 'kiwi', 'selected': false}
];

  $scope.printFruits = function(){return JSON.stringify($scope.fruits);}
}

и немного настоящего тупого HTML

<div ng-app>
  <div ng-controller="TodoCtrl">      
     <ul>
       <li ng-repeat="item in fruits">
         {{item['fruit']}}
         <input type="checkbox" ng-model="item['selected']" />
       </li>
     </ul>
    <span>{{printFruits()}}</span> <!-- Works correctly as items are checked -->
  </div>
</div>

Вы можете попробовать переместить свой доступ к ctrl.fruits в тот же div, который работает как контроллер; вы можете не получить fre $watch, потому что ваш доступ не находится в той же области, что и контроллер, который запускает флажки.

person Hylianpuffball    schedule 07.01.2014