2

I'm trying to show an arrow icon to be used as "go to top" button, but only after some scrolling done by the user. The code used to work great using jquery, but I'm having hard time to achieve the same effect using angular. At the moment, the arrow is always seen in the bottom right corner of the screen.

JSfiddle here.

JS:

var myApp = angular.module('app',[]);

myApp.controller('ctrl', ['$scope', function($scope) {
     //detect scroll
    $(window).scroll(function (event) {
    var scroll = $(window).scrollTop();
        console.log(scroll);
        if(scroll>500 || scroll==undefined){
            $scope.showUpArrow = false;
        }else{
            $scope.showUpArrow = true;
        }
    });
}]);

HTML:

<div ng-app="app">
  <div ng-controller="ctrl">
    <div ng-hide="showUpArrow" id="goUp-cont">
      <a href="#top"><i class="fa fa-arrow-up fa-4x" id="goUp"></i></a>
    </div>
  </div>
</div>
Alex
  • 1,982
  • 4
  • 37
  • 70
  • 1
    See this answer... do it the angular way if you can... http://stackoverflow.com/questions/26319551/angularjs-scrolltop-equivalent – OliverJ90 Jan 12 '16 at 13:59

2 Answers2

3

You gonna need to manually $apply() (or $digest()) your scope, as you are in a jquery handler, so basically outside of angular cycle.

myApp.controller('ctrl', ['$scope', function($scope) {
     //detect scroll
    $(window).scroll(function (event) {
    var scroll = $(window).scrollTop();
        console.log(scroll);
        if(scroll>500 || scroll==undefined){
            $scope.showUpArrow = false;
        }else{
            $scope.showUpArrow = true;
        }
        **$scope.$apply();**
    });
}]);

should basically fix your problem

To avoid expensive digestion cycles on each scroll event when they are, most of the time, useless, you should also check the initial value of showUpArrow, triggering the digest cycle only if the value changed :

myApp.controller('ctrl', ['$scope', function($scope) {
     //detect scroll
    $(window).scroll(function (event) {
    var scroll = $(window).scrollTop();
    var oldState = $scope.showUpArrow;
        console.log(scroll);
        if(scroll>500 || scroll==undefined){
            $scope.showUpArrow = false;
        }else{
            $scope.showUpArrow = true;
        }
        if($scope.showUpArrow !== oldState) {
            $scope.$apply();
        }
    });
}]);
Pierre Gayvallet
  • 2,933
  • 2
  • 23
  • 37
  • Thanks for the answer. Only one thing, the arrow is seen when the page first loads, why is so? `showUpArrow` is first evaluated to `false`. – Alex Jan 12 '16 at 14:07
  • 1
    @undroid, it is first evaluated to `false` because you have `ng-hide="showUpArrow"` in your HTML. It should be `ng-show="showUpArrow"`, i updated [a fiddle with those modifications](http://jsfiddle.net/8hn5cws7/4/) – arainone Jan 12 '16 at 14:45
2

A call $scope.apply() is missing:

$(window).scroll(function (event) {
    var scroll = $(window).scrollTop();
    console.log(scroll);
    if(scroll>500 || scroll==undefined){
        $scope.showUpArrow = false;
    }else{
        $scope.showUpArrow = true;
    }
    $scope.$apply();
});

See it working on updated fiddle

More info on why you have to do this: here for example

arainone
  • 1,928
  • 17
  • 28