ste ste - 1 year ago 73
AngularJS Question

Binding directive scope with controller in AngularJS

I'm using a directive to check how much the user is scrolling the window but I can't manage to bind the scope with the controller.

Here's the directive and controller code:

'use strict';

angular.module('myApp.landing', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
.controller('landingCtrl', ["$scope", function($scope) {
$scope.scrolled = false;

$scope.$on('$routeChangeSuccess', function() {
directive("scroll", ["$window", function($window){
return {
scope: false,
link: function($scope, element, attrs){
angular.element($window).bind("scroll", function(){
if (this.pageYOffset >= 150) {
$scope.scrolled = true;
console.log($scope.scrolled + 'Scrolled 100px');
} else {
$scope.scrolled = false;
console.log($scope.scrolled + 'Not scrolled enough');

this is the view code:

<div ng-controller="landingCtrl" scroll>
<div class="row">
<div class="col-sm-12 col-md-9 landing-square">{{ scrolled }}</div>
<div class="col-sm-12 col-md-3 landing-square"></div>

In the view scrolled is not defined. If I define it in the controller I can see it, but the directive can't change its value. Basically I want in the view the variable "scrolled" that is changing value according to the directive.

What am I missing?


Because you're changing a something on the scope in a place Angular does not "know" about (e.g. a custom DOM event handler), you need to explicitly tell it to apply that change:

angular.element($window).bind("scroll", function(){
    if (this.pageYOffset >= 150) {
         $scope.$apply(function() { $scope.scrolled = true; });
         console.log($scope.scrolled + ' Scrolled 100px');
     } else {
         $scope.$apply(function() { $scope.scrolled = false; });
         console.log($scope.scrolled + ' Not scrolled enough');

See this example, and see this excellent Q&A on $scope $apply and $watch. Or just go straight to the relevenat documentation (which is dry/technical, but explains the reasoning bhind it as well).