Как получить асинхронный атрибут html

#angularjs

#angularjs

Вопрос:

У меня есть список элементов, восстановленных асинхронным вызовом, и этот список отображается с помощью ng-repeat . Поскольку контейнер div этого списка имеет фиксированную высоту (400 пикселей) Я хочу, чтобы полоса прокрутки была внизу. И для этого мне нужно scrollHeight . Но scrollHeight in postLink — это не конечная высота, а начальная высота.

Пример

ppChat.tpl.html

 <!-- Height of "chatroom" is "400px" -->
<div class="chatroom">
  <!-- Height of "messages" after all messages have been loaded is "4468px" -->
  <div class="messages" ng-repeat="message in chat.messages">
    <chat-message data="message"></chat-message>
  </div>
</div>
 

ppChat.js

 // [...]
compile: function(element) {
  element.addClass('pp-chat');

  return function(scope, element, attrs, PpChatController) {
    var messagesDiv;
    // My idea was to wait until the messages have been loaded...
    PpChatController.messages.$loaded(function() {
      // ...and then recompile the messages div container
      messagesDiv = $compile(element.children()[0])(scope);
      // Unfortunately this doesn't work. "messagesDiv[0].scrollHeight" still has its initial height of "400px"
    });
  }
}
 

Может кто-нибудь объяснить, что я здесь пропустил?

По мере необходимости вот его часть

Комментарии:

1. пожалуйста, создайте plunkr, чтобы другие могли редактировать / улучшать ваш код.

2. откуда у вас высота прокрутки 2000 пикселей?

Ответ №1:

Вы можете получить scrollHeight из div после обновления DOM, выполнив это следующим образом.

Приведенная ниже директива устанавливает наблюдение за массивом, то есть коллекцией, и использует службу $timeout для ожидания обновления DOM, а затем прокручивается до нижней части div.

 chatDirective.$inject = ['$timeout'];

function chatDirective($timeout) {
  return {
    require: 'chat',
    scope: {
      messages: '='
    },
    templateUrl: 'partials/chat.tpl.html',
    bindToController: true,
    controllerAs: 'chat',
    controller: ChatController,
    link: function(scope, element, attrs, ChatController) {
      scope.$watchCollection(function () {
        return scope.chat.messages;
      }, function (newValue, oldValue) {
        if (newValue.length) {
          $timeout(function () {
            var chatBox = document.getElementsByClassName('chat')[0];
            console.log(element.children(), chatBox.scrollHeight);
            chatBox.scrollTop = chatBox.scrollHeight;
          });
        }
      });
    }
  };
}
 

Обновленный плунжер находится здесь.

Также в вашем контроллере вы написали как,

   var Controller = this;

  this.messages = [];
 

Лучше писать так, здесь vm означает ViewModel

 AppController.$inject = ['$timeout'];

function AppController($timeout) {
  var vm = this;

  vm.messages = [];

  $timeout(
    function() {
      for (var i = 0; i < 100; i  ) {
        vm.messages.push({
          message: getRandomString(),
          created: new Date()
        });
      }
    },
    3000
  );
}