Question

I'm new to AngularJS and already on the brink of despair :) My app looks like this (Not-working example on Plnkr):

HTML

<div ng-app="myApp" ng-controller='controllers.content' >
  <h2 id="fixed">{{ header }}</h2>
  <ul>
    <li ng-repeat="item in db" scroll-stop="item">{{ item.name }}</li>
  </ul>
</div>

JS

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

var app = angular.module('myApp.controllers').controller('controllers.content', ['$scope', function($scope){
    $scope.db = [
      { name: "20 February 2014", header: "Today" },
      // ...
    ];
    $scope.header = "Today";
}]);

Now basically I want a scroll spy that changes the contents of the h2 (assume it's fixed to the top) to the header property of the item in db whenever that item is currently at the top of the viewport:

app.directive('scrollStop', function() {
   return {
        restrict: 'A',
        scope: {
          scrollStop:'='
        },
        link: function (scope, element, attrs) {

            var $page = angular.element(window)
            var $el   = element[0]
            var last_top = $el.getBoundingClientRect().top - 60;
            $page.bind('scroll', function () {
                var current_top = $el.getBoundingClientRect().top - 60;
                if (last_top >= 0 && current_top < 0) {
                    // HERE!
                    console.log(scope.scrollStop.header);
                    scope.header = scope.scrollStop.header;
                }
                last_top = current_top;
            })

        }
    }
});

However, I can't figure out how to talk to the content controller from within the directive to edit $scope.header from within the directive. I understand that the scope is a different to the controller's $scope, and have a vague feeling that I should use require somewhere, but can't figure out how to get it right. Partly also because there seem to be 5 different shorthands for doing anything in AngularJS and they don't always go well together. Any help appreciated, including stylistic guidance.

Was it helpful?

Solution

You are using isolated scope for you directive. So you canot access to the scope controller. You could comunicate with the controller using a service or using events.

If you want to be able to access to the controller scope directly from your directive, you have to use shared scope.

I hope that it helps. You can find more information about scopes in directives Here.

-----------EDIT----------------

I am not sure what you want to do, but in the next code you can see as using share scope, you can acces the data from de parent and making the view refresh with the new data.

angular.module('app').directive('scrollStop', function() {
    return {
        restrict: 'A',
        scope: false,
        link: function (scope, element, attrs) {

            var $page = angular.element(window)
            var $el   = element[0]
            var last_top = $el.getBoundingClientRect().top - 60;
            $page.bind('scroll', function () {
                var current_top = $el.getBoundingClientRect().top - 60;
                if (last_top >= 0 && current_top < 0) {
                    // HERE!
                    scope.$parent.header=scope[attrs.scrollStop].header;
                    scope.$parent.$apply();
                }
                last_top = current_top;
            })

        }
    }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top