0

Я использую AngularJS с директивой ng-repeat.
Мне действительно нужно знать, есть ли способ связать события типа «ng-repeat-before-render» и «ng-repeat-after-render». Мне нужно, что по нескольким причинам один из них предназначен для вычисления высоты до и после рендеринга.
Я видел несколько директив, которые полагаются на $scope.$last, но $scope.$last верен только при рендеринге последнего элемента в последовательности, и в моем случае я добавляю элементы в середине списка.angularjs ng-repeat после рендера

Я очень ценю направление решения этой проблемы.

+0

Какое требование .. может быть, вам действительно не понадобится до-после рендера – harishr

+0

@HarishR У меня есть список элементов и полоса прокрутки (с использованием jQuery perfect scrollbar). Прокрутка вверх в списке загружает больше предметов (вверх, а не вниз, как люди привыкли). После рендеринга сообщений я обновляю полосу прокрутки. Проблема в том, что полоса прокрутки остается в верхней части списка, а перемещается в середину. Эта проблема может быть решена без событий ngRepeat, но мне действительно нравится знать, какие опции ngRepeat дают, чтобы делать что-то после рендера. – Naor

+0

см. Функции pre/post link: http: // stackoverflow.com/questions/18297208/post-link-vs-pre-link-in-angle-js-директивы –

ответ

1

Использование $ evalAsyc для перед визуализацией и $ таймаут после рендеринга:

link: function(scope, element,attr){ 
     scope.$evalAsync(function(){ 
       // executes after compile/link 
       // and before render 
     }) 
     $timeout(function(){ 
       // executes after render 
     }) 
}) 
+0

Функция связи выполняется для каждого элемента ретранслятора. Я ищу сингл «before» и сингл «after». Если у меня 20 элементов, эти методы будут выполняться 20 раз. – Naor

+0

Создайте родительскую директиву вне вашего ng-repeat. В угловом выражении нет явного перед рендером и после событий рендеринга. Но $ evalAsync и $ timeout выполнит то же самое. – pixelbits

+0

$ evalAsync на самом деле действительно хороший ответ. Просто он не решает «только один раз» часть запроса. Но вы можете сделать это с помощью простого механизма отладки, и вы находитесь дома ... –

0

К сожалению, ngRepeat не дает то, что вы просите. ngRepeatStart/End - это только маркеры, где последовательность начинается/заканчивается, а не где начинается рендеринг. (Используется для таких вещей, как создание верхних и нижних колонтитулов из некоторых строк в наборе или, может быть, простая разбивка на страницы).

Реальная проблема с рендерингом заключается в том, что вы никогда не знаете, где вы на самом деле находитесь в цепочке рендеринга, когда вы в углу. Директива, подобная той, которую вы хотите, будет трудно/невозможна даже для создания. Когда Angular начинает рендеринг, он начинает «гулять» по DOM, глядя на каждый элемент/дочерний элемент и «компилируя» эти элементы по мере его появления. В любое время операции пересылки могут привести к запуску целой новой последовательности. Вы видите это много с помощью специальных директив типа элемента.

Угловые концы делают это за два прохода: скомпилируйте и соедините. Пока вы не дойдете до стадии ссылки, что вы даже можете мечтать о вычислении высоты элемента, потому что именно там объекты фактически добавляются в DOM. Но на этом этапе вы все еще в основном потоке (у JS есть только один), поэтому браузер, вероятно, еще не успел рассчитать его!

Мое предложение было бы изменить тактику. Используйте какое-то средство отладки и средство setImmediate, чтобы обработать цикл обработки, что он делает, а затем выполнить какие-либо из ваших обновлений проверки размера, требуемых в этот момент. Вы можете легко обнаружить, когда элемент нуждается в этом, с простой директивой - любая директива с ЛЮБОЙ функцией ссылки вообще будет иметь, что вызывается, когда элемент визуализируется.

Так что мои предложения является:

  1. Написать "iWasDrawn" директиву с простой функцией связи.
  2. В этой функции связи вызовите функцию «debounce» или «setImmediate» с помощью debounce - выберите ваш выбор, есть десятки.
  3. В этом обратном вызове сделайте свой расчет размера.

Это должно быть эффективно, оно должно работать, и это довольно просто.

+0

Я думал об использовании дебюта и даже сделал это. Проблема в таком решении заключается в том, чтобы найти точное время для функции debounce. Меньшее время вызовет неправильное выполнение обратного вызова. Больше времени вызовет прыжки ui. – Naor

+0

Взгляните на [setImmediate] (https://github.com/YuzuJS/setImmediate), плагин, который поможет решить эту проблему. Это супер быстрый обратный вызов, и вы можете связать его с clearImmediate для debounce (clearImmediate, за которым следует setImmediate, очистит предыдущие, но еще не выполненные вызовы, а затем вы можете установить один последний). –

+0

Это звучит как супер-сильное решение, но все же, похоже на хак .. – Naor

Смежные вопросы