Как изменить результаты только для чтения ng-приложения? - PullRequest
2 голосов
/ 04 марта 2020

Я прошу прощения, если это дубликат, но я не смог найти ничего похожего на это.

Компания, в которой я работаю, имеет систему онлайн-отчетности, которая управляется приложением ng-app непосредственно к тегу body. Мне было поручено изменить результат, который возвращается из этого приложения нг. Следующий код вызывается с использованием onload, прикрепленного к тегу body.

function getElements(){
  var list;
  list = document.getElementsByClassName("neutral");
  [].forEach.call(list, function (listItem) {
       addNeutral(listItem);
  });

...

По сути, попытка найти что-либо с классом «нейтральный» и применить к нему результаты другой функции. Функция addNeutral в основном просто

element.classList.add("neutralHighlight");

Этот код, кажется, выполняется и собирает правильный список элементов, но новый класс никогда не добавляется, и ошибок не возникает. Короче говоря, есть ли способ изменить вывод ng-приложения, используя код, отдельный от самого ng-приложения? Любое руководство будет с благодарностью.

Обновление 3/5/20

Поэтому я реализовал ответ Шона, и он все еще не работает должным образом. С некоторыми отладочными сообщениями я вижу, что он собирает переменную «list» как HTMLCollection. Функция forEach, похоже, даже не запускает

function getElements(){
  var list;
  list = document.getElementsByClassName("neutral");
  console.log(list); //Debug - Shows in console
  [].forEach.call(list, function (listItem) {
       console.log(listItem); //Debug - Does not show in console
       addNeutral(listItem);
  });
  }

  function addNeutral(element){
    angular.element(element).addClass("neutralHighlight"); 
    console.log("!!!end addNeutral"); //Debug - Does not show in console
  }

Обновление 3/9/20 -SOLUTION-

Приложение возвращает коллекцию HTML, но отображается с длиной 0 (по-прежнему отображает объекты, но я думаю, что это Firefox консольная вещь). При попытке выполнить l oop через элементы списка он возвращает ноль для первого элемента, поэтому функция все еще вызывается до полной загрузки приложения Angular.

Как говорится, сегодня утром я немного повозился с вещами и пришел к решению! В итоге я использовал функцию setInterval с 5-секундным интервалом (так как мне нужно обновить его, я могу изменить это, чтобы оптимизировать его позже, добавив элементы onChange к объектам, которые я получаю изначально). Предложенное значение setTimeout работало бы с добавленной задержкой. Это, вероятно, не самое элегантное решение, и, возможно, есть лучший способ сделать это, но это работает для всех, кто заинтересован.

function getElements(){
  var list;
  list = document.getElementsByClassName("neutral");
  for (i = 0; i <= list.length; i++){
    var listItem = list.item(i);
    addNeutral(listItem);
  }
}

function loadFunction(){
  setInterval(function(){getElements()}, 5000);
}

Я добавил <script>loadFunction()</script> прямо перед закрывающим тегом HTML для выполнения.

Обновление 4/21/20 - УЛУЧШЕННОЕ РЕШЕНИЕ- CSS Атрибуты

Так что это немного специфицирует c для моего сценария, но я хотел бы включить его для всех, кто может столкнуться с этим в будущем. Я действительно смог выполнить sh полностью с помощью CSS селекторов атрибутов. У всех тегов, которые я хотел отредактировать, были определенные c заголовки, назначенные им через приложение ng, предоставленное компанией, поэтому я мог использовать CSS селекторы, такие как div [title~="NotReadyForNextCall"]{<custom styling here>}, чтобы выбрать любой блок, включающий агента, который не был готов к их следующему звонку. Это гораздо лучшее решение с точки зрения ресурсов, необходимых для работы и общей производительности, поэтому я надеюсь, что это поможет любому взглянуть на это в дальнейшем!

1 Ответ

1 голос
/ 04 марта 2020

Вы можете обойти это, используя объект angular в своем коде и добавив класс вместо angular.element. AngularJS не использует виртуальный DOM, но использует собственные ссылки на узлы (что делает работу с внешней средой настолько сложной, как указал Лекс в комментариях к вашему вопросу). Попробуйте:

angular.element(element).addClass("neutralHighlight");

Да, у вас есть доступ к angular вне приложения! И последнее замечание, addClass() доступно на angular.element, потому что AngularJS поставляется с jqLite.


Дальнейшее исследование

Похоже как и вышеупомянутое решение работает, если класс 'нейтральный' добавляется в angular через атрибут class, но похоже, что ваше приложение может добавлять его программно с помощью директивы ng-class после рендеринга DOM.

Я обернул вашу getElements() функцию в setTimeout():

setTimeout(getElements);

К сожалению, это не гарантия того, что обновление ng-class будет иметь место, но то, что оно делает, оно выполняет функция после завершения предыдущего цикла дайджеста, и, похоже, она работает.

Еще более безопасным решением было бы использование document.ready, но снова с оболочкой angular.element. Это обеспечит исходное состояние DOM для AngularJS, включая примененные директивы:

angular.element(document).ready(function() {
  getElements();
});

EDIT: обновление 3/9/20 -SOLUTION-

Решение, предложенное в ответе, практически идентично ответу setTimeout(), приведенному здесь. Единственная разница в том, что setInterval() будет продолжать выполнять код каждые 5 секунд, пока вы не скажете ему остановиться.

Вы можете сделать это с помощью следующего:

var loadFunction = setInterval(function() {
  var el = getElements();
  if (el) clearInterval(loadFunction);
}, 5000);

И просто вернуть bool в вашем getElements() вот так:

function getElements() {
  var list;
  var found = false;
  list = document.getElementsByClassName("neutral");
  [].forEach.call(list, function (listItem) {
       addNeutral(listItem);
       found = true;
  });
  return found;
}

См .: codepen.io / shaunetobias / pen / KKpXRxq

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...