23

Ho can I get the window width in angularJS on resize from a controller? I want to be able to get it so I can display some div with <div ng-if="windowWidth > 320">

I can get the windowWidth on the initial page load but not on resize...

'use strict';

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

app.controller('mainController', ['$window', '$scope', function($window, $scope){
	var mainCtrl = this;
	mainCtrl.test = 'testing mainController';
  
    // Method suggested in @Baconbeastnz's answer  
    $(window).resize(function() {
      $scope.$apply(function() {
        $scope.windowWidth = $( window ).width();
      });
    });
  
    /* this produces the following error
    /* Uncaught TypeError: mainCtrl.$digest is not a function(…)
    angular.element($window).bind('resize', function(){
        mainCtrl.windowWidth  = $window.innerWidth;
        // manuall $digest required as resize event
        // is outside of angular
        mainCtrl.$digest();
    });  
    */
}]);

// Trying Directive method as suggested in @Yaser Adel Mehraban answer.
/*app.directive('myDirective', ['$window', function ($window) {
     return {
        link: link,
        restrict: 'E'            
     };
     function link(scope, element, attrs){
       angular.element($window).bind('resize', function(){
           scope.windowWidth = $window.innerWidth;
       });    
     }    
 }]);*/
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<body ng-app="app" ng-controller="mainController as mainCtrl">
	<p>{{mainCtrl.test}}</p>
	<hr />
    <p ng-if="windowWidth > 600">The window width is {{windowWidth}}</p>
    <div my-directive ng-if="windowWidth > 320">It works!</div>
</body>

I see in this answer they explain how you can get it from within a directive but how can you get it to work from within a controller?

2
  • Just wondering, wouldn't it be better to handle resize issues with CSS? Commented May 9, 2017 at 15:23
  • 1
    @Harke There are some use cases where CSS won't cut it. For example, I need to display a large amount of tabular data. Using a <table> element makes sense on desktop, but won't work on mobile. Hiding it just with CSS isn't the best idea either, as the data will get rendered twice (even though it only displays once). Commented Jun 19, 2018 at 20:30

4 Answers 4

26

The best way is to use a directive and watch for resize event of the window:

'use strict';

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

app.directive('myDirective', ['$window', function ($window) {

     return {
        link: link,
        restrict: 'A'           
     };

     function link(scope, element, attrs){

       angular.element($window).bind('resize', function(){
           scope.windowWidth = $window.innerWidth;
       });    
     }    
 }]);

And use it on your div:

<div my-directive ng-if="windowWidth > 320">

Here is a working plunker.

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

2 Comments

this seems like the best approach but it doesn't work in the code snippet. I updated the code snippet in my question with this and it still does not work.
The .bind function is deprecated, so better to use .on. docs.angularjs.org/api/ng/function/angular.element
7

Finnally got it working with the below. Took most of the code from https://stackoverflow.com/a/23078185/1814446.

The only difference was for the ng-if to work the directive had to be put on a parent html element.

'use strict';

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

app.controller('mainController', ['$window', '$scope', function($window, $scope){
	var mainCtrl = this;
	mainCtrl.test = 'testing mainController';
}]);

app.directive('windowSize', function ($window) {
  return function (scope, element) {
    var w = angular.element($window);
    scope.getWindowDimensions = function () {
        return {
            'h': w.height(),
            'w': w.width()
        };
    };
    scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {
      scope.windowHeight = newValue.h;
      scope.windowWidth = newValue.w;
      scope.style = function () {
          return {
              'height': (newValue.h - 100) + 'px',
              'width': (newValue.w - 100) + 'px'
          };
      };
    }, true);

    w.bind('resize', function () {
        scope.$apply();
    });
  }
})
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<body window-size my-directive ng-app="app" ng-controller="mainController as mainCtrl">
  <p>{{mainCtrl.test}}</p>
  <hr />
  <div ng-if="windowWidth > 500">
    <h4 style="margin:5px 0">It works!</h4>
    <p style="margin:0">window.height: {{windowHeight}}</p>			     <p style="margin:0">window.width: {{windowWidth}}</p>			     <p style="margin:0">{{mainCtrl.test}}</p>
  </div>
</body>

Comments

6

Getting the window width on resize isn't anything specific to Angular JS. in fact Angular doesn't provide any capability to do it. It's native javascript, the native window object fires a resize event that you can access. jQuery provides a handy wrapper for this. By using a simple callback in your controller and then updating your double bound windowWidth property on the $scope object you can get the functionality you need without using a directive.

$(window).resize(function() {
  $scope.windowWidth = $( window ).width();
});

4 Comments

May you explain your answer?
Getting the window width on resize isn't anything specific to Angular JS. in fact Angular doesn't provide any capability to do it. It's native javascript, the native window object fires a resize event that you can access. jQuery provides a handy wrapper for this. By using a simple callback in your controller and then updating your double bound windowWidth property on the $scope object you can get the functionality you need without using a directive.
@Baconbeastnz , thanks but when I tried this in the Code Snippet from my question it does not work, see updated Code Snippet in my question
You weren't doing a few things correctly. Have fixed code snippet for you. Basically you need to use $scope instead of 'this'. Also, because the window resize event happens outside the Angular domain, you need to call $scope.apply to manually inform Angular to re-apply changes
4

Just include this code in your controller and you will get the new window width every time.

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

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.