2016-01-14 4 views
2

У меня проблема с обновлением css на элементе в Angular. У меня есть div, который содержит элементы, генерируемые ng-repeat. div, содержащий эти элементы, имеет высоту набора и имеет прикрепленную к нему директиву ng-scrollbars. ng-scrollbars создает приятную полосу прокрутки внутри div, когда элементы в div превышают высоту их контейнера. Для этого он создает вложенные внутренние div. Поэтому в этом случае, если высота вложенных внутренних divs больше, чем их контейнер, то полоса прокрутки будет сделана так, чтобы вы могли прокручивать элементы.Угловая не обновляется css после ng-repeat

Так что скажем, я добавляю или удаляю элементы в список ng-repeat. Когда это произойдет, я хотел бы добавить дополнительный css к верхнему уровню div , только если внутренний div, сделанный ng-scrollbars, превышает высоту div верхнего уровня. (высота внутреннего div является фактической высотой списка ng-repeat, поскольку содержит элементы ng-repeat)

Для этого я создал две директивы, которые передают событие и тот, который его получает. Тот, который транслирует событие, привязан к каждому элементу ng-repeat и транслируется, когда элемент создается или уничтожается. Это нужно проверить, когда происходят изменения в списке ng-repeat.

Тот, который принимает передачу прикреплен к верхнему уровню div контейнера (тот, который содержит DIV, сделанное ng-scrollbar) и проверяет его высоту относительно внутренней DIV, сделанных ng-scrollbar, если высота внутреннего DIV больше, чем верхний уровень div, тогда добавьте некоторый css.

Я сожалею, если это кажется запутанным, вот мой код делает это с комментариями прилагается, что я надеюсь объяснить это лучше:

app.directive('gtScrollLb', function() { 
    return { 
    restrict: 'A', 
    link: function (scope, elem, attrs) { //elem is the top level container of the ng-repeat elements 
     var scrollDiv = elem.children()[0]; //this is an internal div created by ng-scrollbars 
     var anotherScrollDiv = $(scrollDiv).children("#" + $(scrollDiv).attr("id") + "_container"); //another internal div created by ng-scrollbars 
     var id = attrs.gtScrollLb; 

     scope.$on(id + "-repeat-change", 
     function(newVal, oldVal) { 
      //check if ng-scrollbar div that now contains the ng-repeat elements 
      //has a greater height than the top level container 
      if ($(anotherScrollDiv).height() >= elem.height()) { 
       elem.css("border-bottom", "1px solid darkgrey"); 
      } else { 
       elem.css("border-bottom", ""); 
      } 
     } 
    ); 
    } 
    }; 
}); 

app.directive('gtRepeatable', function() { 
    return { 
    restrict: 'A', 
    link: function (scope, elem, attrs) { 
     var id = attrs.gtRepeatable; 
     scope.$emit(id + "-repeat-change"); //event that item has been added by ng-repeat 
     var parent = scope.$parent; 
     elem.bind("$destroy",function(){ 
     parent.$broadcast(id + "-repeat-change");//event that item has been destroyed by ng-repeat 
     }); 
    } 
    } 
}); 

Проблема в том, что ng-repeat элементы добавляются и уничтожены до того в высота их внутреннего контейнера определяется снова. Таким образом, высота, проверяемая при запуске события изменения, на самом деле является старой высотой внутреннего контейнера.

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

Редактировать

В общем, мне нужно еще стрелять или $ смотреть произойдет после нг-повтора закончил и DOM оказал. Проблема, которая возникает у меня здесь, происходит только потому, что событие уволено до DOM.

Edit 2

Для @vittore, который попадает это как дубликат. Если вы действительно подробно прочитали мой вопрос, вы увидите, что тот, который вы предложили в качестве дубликата, не имеет ничего общего с моей реальной проблемой. Здесь нет проблем с ng-scrollbars. ng-scrollbars работает нормально. Но нужно было включить его в описание, потому что оно влияет на то, как я собираюсь решить мою проблему.

+1

Создайте демоверсию, которая реплицирует проблему – charlietfl

+0

@charlietfl код, связанный с этой проблемой, - это много, чтобы попробовать и реплицировать в jsFiddle. Есть ли что-то, в чем я могу подробно остановиться? – Graham

+0

если мы не можем его увидеть или воспроизвести, как кто-нибудь может помочь? – charlietfl

ответ

0

Чтобы получить эту работу я закончил с использованием MutationObservers. Я должен был использовать два, один для изменений атрибутов и один для изменений в списке дочерних списков.

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

Лучше всего подключить их непосредственно перед внесением изменений в DOM и отключить их после внесения изменений.

+0

Не лучший способ, но разве вы не могли проверить высоту после некоторого $ timeout? – John

+0

@ Джон, конечно, и риск, связанный с загрузкой css, так что он, похоже, отстает от пользователя. Или риск, что он проверен слишком рано, а затем css не загружается вообще. MutationObservers отлично подходят, если вы правильно управляете ими, как описано здесь. $ timeout - разработчик, ленивый, на мой взгляд. – Graham

0

Существует способ получить событие, когда последний элемент цикла был renderd.Проверить эту ссылку: AngularJS - Manipulating the DOM after ng-repeat is finished

Также здесь точно вопрос у вас есть: ng-scrollbar is not working with ng-repeat

и важная часть:

$scope.$on('loopLoaded', function(evt, index) { 
    if (index == $scope.me.length-1) { 
     $scope.$broadcast('rebuild:me'); 
    } 
    }); 
+0

Это не точный вопрос .... моя ng-прокрутка работает отлично. Пожалуйста, прочтите мой оригинальный вопрос, и вы увидите, что он не имеет ничего общего с неисправностью ng-scrollbar. – Graham

+0

@ Graham вы пробовали фрагмент кода, который я включил? он показывает, как транслировать событие ПОСЛЕ того, как последний элемент отображается, все, что вам осталось сделать, это прослушать его с помощью '$ scope. $ on' – vittore

+0

** Отделить его ** часть сообщения может работать ... но это также может не. В моем конкретном случае я запускал события при каждом создании и уничтожении 'ng-repeat'. Таким образом, он по существу делал то же самое, что и с использованием '$ last'. Я решил свою проблему с MutationObservers и правильно управляю ими, только активируя их прямо перед тем, как изменение должно быть выполнено, а затем дезактивировать себя после внесения изменений. Это не оставляет накладных расходов. И было относительно просто. – Graham

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