Компонент Angular-Dart не всегда отображается в веб-приложении

В нашем приложении Angular-dart определены некоторые компоненты (@NgComponent). В первый раз такой компонент отображается, он отображается правильно. Со второго раза компонент иногда отображается в веб-приложении, иногда - нет. Отладка указывает, что код компонента выполняется, даже если он не показан. Похоже, что никаких исключений / трассировок стека не происходит. При попытке отследить проблему мы позволили Компоненту реализовать NgShadowRootAware и добавили метод void onShadowRoot (ShadowRoot shadowRoot) {}. Каждый раз, когда в метод onShadowRoot ставится точка останова, компонент отображается правильно. Когда точка останова удалена, большую часть времени HTML-компонент не отображается в веб-приложении.

Очевидно, изменение размера (несколько раз) окна браузера заставляет компонент отображаться.

view_objectdata_component.dart

library view_objectdata_component;

import 'package:angular/angular.dart';
import 'dart:html';
import '../model/model.dart';


@NgComponent(
    selector: 'view-objectdata',
    cssUrl: '../lib/component/view_objectdata_component.css',
    templateUrl: '../lib/component/view_objectdata_component.html',
    publishAs: 'cmp'
)
class ViewObjectDataComponent implements NgShadowRootAware {

  @NgTwoWay('objectdata-map')
  Map<String, ObjectData> dataMap;  
  @NgTwoWay('readonly')
  bool readonly = true;  

  @NgTwoWay('editLink')
  String theEditLink;  

  String _id;

  ViewObjectDataComponent(RouteProvider routeProvider) {
    _id = routeProvider.parameters['id'];
  }

  bool get hasEditLink => theEditLink != null;
  String get editLink => theEditLink.replaceAll('<id>', _id);

  ObjectData get data  {
    ObjectData val = dataMap[_id];
    return val;
  }

  List<ObjectAttribute> get attributes {
    List<ObjectAttribute> list = [];
    for (ObjectAttribute simAtt in data.attributes.values) {
      list.add(simAtt);
    }
    return list;
  }

  void onShadowRoot(ShadowRoot shadowRoot) {
    shadowRoot.querySelector('#myDiv').children.add(
        new SpanElement()..text = ''
    );
  }
}

view_objectdata_component.html

<div id='myDiv'>
  <h3>{{cmp.data.getAttVal('Name')}}</h3>
    <div><strong>ID: </strong>{{cmp.data.id}}</div>
    <ul>    
      <li ng-repeat="att in cmp.attributes">
         <view-attributevalue objectattribute="att" readonly="cmp.readonly"></view-attributevalue>
      </li>
    </ul>
  <span ng-if="cmp.hasEditLink">    
    <a class="extra-space" href="{{cmp.editLink}}">
      <input type="button" value="Edit">
    </a>
  </span> 
</div>

вызвано:

{{ctrl.changeMainSection('applications')}}
<div>
 <br/>
 <div class="alert alert-info alert-dismissable fade in">         
  <view-objectdata 
    objectdata-map="ctrl.asDataMap(ctrl.applications)" editLink="'#/appComp/<id>/edit'"        
  >   
  </view-objectdata>
  </div>
</div>

person hbkn    schedule 13.03.2014    source источник
comment
Скорее всего, проблема в сроках. Вы можете разместить код?   -  person Günter Zöchbauer    schedule 14.03.2014
comment
Я добавил код в сообщение. При необходимости я могу предоставить zip-файл с кодом проекта, который работает с некоторыми локальными демонстрационными данными. версия: Dart Editor версия 1.2.0.release (STABLE) / angular 0.9.8   -  person hbkn    schedule 14.03.2014
comment
Можете ли вы создать репозиторий GitHub с исходным кодом. Я пока не понимаю, как вы «показываете» компонент «второй раз».   -  person Günter Zöchbauer    schedule 14.03.2014
comment
Я могу воспроизвести проблему. Причину пока не нашел.   -  person Günter Zöchbauer    schedule 15.03.2014


Ответы (1)


Я думаю, что когда ваши данные (приложения) загружаются асинхронно из queryService, это обновление не запускает всю цепочку зависимостей. Когда у вас есть точка останова, загрузка данных тем временем заканчивается, а затем отображаются все. Если у вас нет точки останова, Angular выполняет рендеринг и почему-то не распознает изменения данных.

В вашем коде есть некоторые шаблоны, которые не нравятся Angular, что может вызвать такое поведение. (Если вы обновитесь до Angular 0.9.9, вы получите некоторые исключения)

Есть несколько способов сделать что-то вроде

List<ApplicationComponent> get applications каждый раз создает новый список.
String tabClassForMainSection(String section) Angular, похоже, не любит такой код (не уверен, что он должен работать), возможно, ошибка в Angular (https://github.com/angular/angular.dart/issues/738).
Map<String, ObjectData> asDataMap(List list) { возвращает новую коллекцию при каждом вызове.

Возможно, вам стоит подумать о другой стратегии загрузки данных. Вы можете внедрить QueryService в компонент и создать метод async getApplications, который вы вызываете из компонента, например queryService.getApplications().then((data) => updateApplications(data));

Когда вы посмотрите на вывод отладки, я разместил здесь https://github.com/angular/angular.dart/issues/738 вы можете увидеть, как часто Angular вызывает методы для проверки обновлений данных. Это очень неэффективно, если каждый раз создается новая коллекция. Это причина, по которой он больше не поддерживается в 0.9.9.

Надеюсь, это немного поможет.

person Günter Zöchbauer    schedule 15.03.2014
comment
Большое спасибо за ваше расследование и отличный отзыв. Адаптирую код с учетом ваших замечаний. Кстати: обычно компонент отображается при изменении размера окна браузера (но не всегда), поэтому я не уверен, что проблема полностью вызвана тем, как загружаются данные. Как правило, когда окно браузера уменьшается, а увеличивается в размерах, отображается содержимое компонента. Спасибо, и я буду держать вас в курсе (через эту ветку) о результатах. - person hbkn; 15.03.2014
comment
Я думаю, что Angular переоценивает данные о некоторых действиях, а затем, когда он видит, что данные изменились, он обновляет представление. Но это делается не во всех случаях, необходимых для вашего приложения, поэтому иногда ничего не отображается. - person Günter Zöchbauer; 15.03.2014
comment
Вы можете взглянуть на - person Günter Zöchbauer; 15.03.2014
comment
Вы пробовали выполнить сборку на JS и проверить, работает ли он там? У меня есть подозрение, что это проблема Dartium. У меня уже было подобное поведение с элементами Polymer в Dartium. Приложение вроде работает нормально. Весь контент виден в инструментах разработки. Я видел, что некоторые ::before ::after добавляются к каждому <div ng-repeat="att in cmp.data.attributeList" class="form-group"> при изменении размера браузера. Я предполагаю, что это какая-то проблема CSS с Dartium / ShadowDOM - person Günter Zöchbauer; 18.03.2014