Reputation: 3166
I am trying to add class to my sidebar when the viewport is less than or equal to 641px, and I have to watch the width of the window for that case
$scope.$watch(function(){
return $window.innerWidth;
}, function(value) {
if (value <= 641) {
logger.info('!!!less than 641');
vm.singleColumn = true;
};
});
It logs on first load, but when I resize, I have to do some clicks before it triggers again. E.g. I resized then I clicked on an item with ng-click behavior then that is the only time, it logs again.
I've read some of the questions, and it is likely due to $digest and $apply?
Can someone give a light to my confusion.
Upvotes: 7
Views: 3590
Reputation: 768
You need to trigger the digest cycle, or the view does not realize that the value was updated.
$scope.$watch(function(){
return $window.innerWidth;
}, function(value) {
if (value <= 641) {
logger.info('!!!less than 641');
vm.singleColumn = true;
$scope.$apply();
};
});
Upvotes: 7
Reputation: 395
1) What user1162084 says
2) The approach with watch on function(){return $window.innerWidth;} will not work, because the resize of window do not cause the start of $digest cycle.
The $watch expression is reevaluated only in $digest cycle. No $digest cycle = no reevaluation. In angularjs $digest cycle is started:
a) After code in ng-click was executed
b) After function in $timeout or $interval was executed.
c) After http request made with $http was finished and success\error handler was executed
There may be and other cases, but the point is that resize of window do not belong to those types of events, which lead to start of $digest cycle.
And this also explains why with code you provided you get update only after ng-click execution
Upvotes: 1
Reputation: 462
According to me you can try directive and check the window resize using jquery and update your variable accordingly. I got an example here please check
var app = angular.module('miniapp', []);
function AppController($scope) {
/* Logic goes here */
}
app.directive('resize', 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();
});
}
})
div {
border:1px solid red;
}
<div ng-app="miniapp" ng-controller="AppController" ng-style="style()" resize>window.height: {{windowHeight}}
<br />window.width: {{windowWidth}}
<br />
</div>
please let me know if this works
Upvotes: 1