0

I'm struggling creating a directive to assign and update a variable, that compares to the window width, and updates with resize.

I need the variable as compared to using CSS because I will work it into ng-if. What am I doing wrong? Here is the code:

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

function AppController($scope) {}

app.directive('widthCheck', function ($window) {
    return function (scope, element, attr) {

        var w = angular.element($window);
        scope.$watch(function () {
            return {
                'w': window.innerWidth
            };
        }, function (newValue, oldValue, desktopPlus, isMobile) {
            scope.windowWidth = newValue.w;
            scope.desktopPlus = false;
            scope.isMobile = false;
            scope.widthCheck = function (windowWidth, desktopPlus) {
                if (windowWidth > 1399) {
               scope.desktopPlus = true;
              }
              else if (windowWidth < 769) {
                scope.isMobile = true;
              }
              else {
                scope.desktopPlus = false;
                scope.isMoblie = false;
              }
            }

        }, true);

        w.bind('resize', function () {
            scope.$apply();
        });
    }
}); 

JSfiddle here: http://jsfiddle.net/h8m4eaem/2/

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Dennis Pitt
  • 89
  • 1
  • 1
  • 9

3 Answers3

0

scope.widthCheck is assigned an anonymous function and RE-ASSIGNED that same function each time this watcher fires. I also notice it's never called.

you should move that piece out of the $watch and call the function when the watcher fires

Jun Duan
  • 218
  • 1
  • 9
0

There's no need for a watch, you're already binding to resize. Just move your logic in there. And as Jun Duan said you continously create the funciton. Here's the change:

app.directive('widthCheck', function ($window) {
    return function (scope, element, attr) {

        function widthCheck(windowWidth) {
            if (windowWidth > 1399) {
                scope.desktopPlus = true;
            }
            else if (windowWidth < 769) {
                scope.isMobile = true;
            }
            else {
                scope.desktopPlus = false;
                scope.isMoblie = false;
            }
        }   
        windowSizeChanged();

        angular.element($window).bind('resize', function () {
            windowSizeChanged();            
            scope.$apply();
        });
        function windowSizeChanged(){
            scope.windowWidth = $window.innerWidth;
            scope.desktopPlus = false;
            scope.isMobile = false;
            widthCheck(scope.windowWidth);
        }
    }
}); 

jsFiddle: http://jsfiddle.net/eqd3zu0j/

Mathew Berg
  • 28,625
  • 11
  • 69
  • 90
0

As mentioned in this SO answer it's probably better to bind to the window resize event with-out watch. (Similar to Mr. Berg's answer.)

Something like in the demo below or in this fiddle should work.

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

function AppController($scope) {}

app.directive('widthCheck', function($window) {
  return function(scope, element, attr) {
    var width, detectFalse = {
      desktopPlus: false,
      isTablet: false,
      isMobile: false
    };

    scope.windowWidth = $window.innerWidth;

    checkSize(scope.windowWidth); // first run

    //scope.desktopPlus = false;
    //scope.isMoblie = false; // typo
    //scope.isTablet = false;
    //scope.isMobile = false;

    function resetDetection() {
      return angular.copy(detectFalse);
    }

    function checkSize(windowWidth) {
      scope.detection = resetDetection();

      if (windowWidth > 1000) { //1399) {
        scope.detection.desktopPlus = true;
      } else if (windowWidth > 600) {
        scope.detection.isTablet = true;
      } else {
        scope.detection.isMobile = true;
      }
    }
    angular.element($window).bind('resize', function() {
      width = $window.innerWidth;
      scope.windowWidth = width

      checkSize(width);
      // manuall $digest required as resize event
      // is outside of angular
      scope.$digest();
    });
  }
});
.fess {
  border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="miniapp" ng-controller="AppController">

  <div width-check class="fess" resize>
    window.width: {{windowWidth}}
    <br />desktop plus: {{detection.desktopPlus}}
    <br />mobile: {{detection.isMobile}}
    <br />tablet: {{detection.isTablet}}
    <br/>
  </div>
</div>
Community
  • 1
  • 1
AWolf
  • 8,770
  • 5
  • 33
  • 39