AngularJS event on window innerWidth size change

JavascriptJqueryAngularjsAngularjs Scope

Javascript Problem Overview


I'm looking for a way to watch changes on window inner width size change. I tried the following and it didn't work:

$scope.$watch('window.innerWidth', function() {
     console.log(window.innerWidth);
});

any suggestions?

Javascript Solutions


Solution 1 - Javascript

We could do it with jQuery:

$(window).resize(function(){
    alert(window.innerWidth);

    $scope.$apply(function(){
       //do something to update current scope based on the new innerWidth and let angular update the view.
    });
});

Be aware that when you bind an event handler inside scopes that could be recreated (like ng-repeat scopes, directive scopes,..), you should unbind your event handler when the scope is destroyed. If you don't do this, everytime when the scope is recreated (the controller is rerun), there will be 1 more handler added causing unexpected behavior and leaking.

In this case, you may need to identify your attached handler:

  $(window).on("resize.doResize", function (){
      alert(window.innerWidth);

      $scope.$apply(function(){
          //do something to update current scope based on the new innerWidth and let angular update the view.
      });
  });

  $scope.$on("$destroy",function (){
      $(window).off("resize.doResize"); //remove the handler added earlier
  });

In this example, I'm using event namespace from jQuery. You could do it differently according to your requirements.

Improvement: If your event handler takes a bit long time to process, to avoid the problem that the user may keep resizing the window, causing the event handlers to be run many times, we could consider throttling the function. If you use underscore, you can try:

$(window).on("resize.doResize", _.throttle(function (){
    alert(window.innerWidth);
    
    $scope.$apply(function(){
        //do something to update current scope based on the new innerWidth and let angular update the view.
    });
},100));

or debouncing the function:

$(window).on("resize.doResize", _.debounce(function (){
     alert(window.innerWidth);
        
     $scope.$apply(function(){
         //do something to update current scope based on the new innerWidth and let angular update the view.
     });
},100));

https://stackoverflow.com/questions/25991367/difference-between-throttling-and-debouncing-a-function

Solution 2 - Javascript

No need for jQuery! This simple snippet works fine for me. It uses angular.element() to bind window resize event.

/**
 * Window resize event handling
 */
angular.element($window).on('resize', function () {
    console.log($window.innerWidth);
});    

Unbind event
/**
 * Window resize unbind event      
 */
angular.element($window).off('resize');

Solution 3 - Javascript

I found a jfiddle that might help here: http://jsfiddle.net/jaredwilli/SfJ8c/

Ive refactored the code to make it simpler for this.

// In your controller
var w = angular.element($window);
$scope.$watch(
  function () {
    return $window.innerWidth;
  },
  function (value) {
    $scope.windowWidth = value;
  },
  true
);

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

You can then reference to windowWidth from the html

<span ng-bind="windowWidth"></span>

Solution 4 - Javascript

If Khanh TO's solution caused UI issues for you (like it did for me) try using $timeout to not update the attribute until it has been unchanged for 500ms.

var oldWidth = window.innerWidth;
$(window).on('resize.doResize', function () {
    var newWidth = window.innerWidth,
	  	updateStuffTimer;

	if (newWidth !== oldWidth) {
	    $timeout.cancel(updateStuffTimer);
	}

	updateStuffTimer = $timeout(function() {
	     updateStuff(newWidth); // Update the attribute based on window.innerWidth
	}, 500);
});

$scope.$on('$destroy',function (){
    $(window).off('resize.doResize'); // remove the handler added earlier
});

Reference: https://gist.github.com/tommaitland/7579618

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLiad LivnatView Question on Stackoverflow
Solution 1 - JavascriptKhanh TOView Answer on Stackoverflow
Solution 2 - JavascriptlinView Answer on Stackoverflow
Solution 3 - Javascriptchris31389View Answer on Stackoverflow
Solution 4 - JavascriptrgpassView Answer on Stackoverflow