5

This is easily done with jQuery:

var msgs = $(".messages ul")

var scroll = false

if( msgs[0].scrollHeight  === (msgs.scrollTop() + msgs.outerHeight() ) )
{

    scroll = true

}
$scope.messages.push(data)
if(scroll)
{

    setTimeout(function(){

        msgs.scrollTop(msgs[0].scrollHeight) // Allow it to update!

    },0)


}

To give some context, ul is the container of the messages, I iterate over the array in $scope.messages and if the container is scrolled to the bottom it will stick to the bottom. This implementation works for me.

Now, I recently learned how one shouldn't really use jQuery in angular. But I am wondering, how would I achieve something like this in pure AngularJS?

1
  • The short answer for most things jQuery to AngularJS is "a directive". But I don't have a specific directive for this one in mind, nor do I yet know the best patterns for creating them so I'll sit and watch the answers with you. Commented Sep 14, 2013 at 15:03

4 Answers 4

8

You can create a directive which will have a variable which when true will go to the top, and will set itself to false once not at top anymore.

How to use:

 <div scroll-to-top="isAtTop">
   <li ng-repeat="stuff in items">{{stuff}}
   <a ng-click="isAtTop = true">Scroll to Top</a>
 </div>

Here's a directive (didn't test, but should work):

angular.module('myApp').directive('scrollToTop', function() {
  return {
    restrict: 'A',
    link: function(scope, elm, attr) {
      var isTop;
      //bind changes from scope to our view: set isTop variable
      //depending on what scope variable is. If scope value
      //changes to true and we aren't at top, go to top
      scope.$watch(attr.scrollToTop, function(newValue) {
        newValue = !!newValue; //to boolean
        if (!isTop && newValue) {
          elm[0].scrollTo(0,0);
        }
        isTop = newValue; 
      });

      //If we are at top and we scroll down, set isTop and 
      //our variable on scope to false.
      elm.bind('scroll', function() {
        if (elm[0].scrollTop !==0 && isTop) {
          //Use $apply to tell angular 
          //'hey, we are gonna change something from outside angular'
          scope.$apply(function() {
            //(we should use $parse service here, but simple for example)
            scope[attr.scrollTop] = false;
            isTop = false;
          });
        }
      });

    }
  };
});
Sign up to request clarification or add additional context in comments.

2 Comments

This is definitely on the right track, how do I make it react to changes from the controller though? I would want it to be a simple check rather than a toggle, that is everytime a new message is inserted the controller calls something. I could simulate it with setting a variable like 'checkScroll' and watch that, but it seems weird.
You would just set $scope.isAtTop to true.
2

I have faced the same issue with table body scrolling. I have resolved it in following way.

Here is my sample html.

<table id="rateplanmapping-scroll">
    <thead>
       <th></th>....
    </thead>
    <tbody >
        <tr ng-repeat="data in datas"> //this is the data
            <td></td>.....
        </tr>
    </tbody>
</table>

Here is the angular code to scroll to the top

angular.element("#rateplanmapping-scroll tbody")[0].scrollTop=0;

I hope it helps. You can put this script in required function, so when particular things happen it get triggered automatically. Or can be attached to event also. I hope it helps.

For div element this can be done in following way

http://plnkr.co/edit/0B4zrFTho6GYuPAS0S1A?p=preview

Comments

2

This is also work $anchorScroll. Example

<div ng-controller="ScrollController">
  <a ng-click="gotoBottom()">Go to bottom</a>
  <a id="bottom"></a> You're at the bottom!
</div>

js:-

.controller(function($scope, $location, $anchorScroll) {
  $scope.gotoBottom = function() {
      // set the location.hash to the id of
      // the element you wish to scroll to.
      $location.hash('bottom');

      // call $anchorScroll()
      $anchorScroll();
    }; 
})

Comments

0

Easiest solution i have seen :

$location.hash('focus');

// call $anchorScroll() $anchorScroll();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.