HTML:
<div ng-app ng-controller="AppController">
boxWidth: {{boxWidth}}
<div ng-show="activeWindow1" style="border:1px solid black; width: {{boxWidth}}px; height:20px;">
</div>
<div ng-show="activeWindow2" style="border:1px solid red; width: {{boxWidth}}px; height:20px;">
</div>
</div>
JS:
function AppController($scope) {
$scope.getWidth = function() {
return $(window).width();
};
$scope.$watch($scope.getWidth, function(newValue, oldValue) {
$scope.boxWidth = newValue / 10;
$scope.activeWindow2 = true;
});
window.onresize = function(){
$scope.$apply();
}
}
JSFiddle: http://jsfiddle.net/fQgXQ/20/
Note that activeWindow1 is never set to true, so technically we should never see the black box, right? Try resizing the window, resulting in the $scope.apply(); call and see what happens.
Result: Both boxes are visible (recent Chrome browser).
There is an easy workaround, which is to take the ng-show out into a new div, making the current one its child. However, I'd like to understand why this is happening as it certainly seems like an Angular bug. I suspect I'm just doing something I'm not supposed to with the {{boxWidth}} inside style="". If so, what's a proper way?
The problem is that the style attribute (from both boxes) is being recalculated after each $apply (because Angular has to interpolate the value from {{boxWidth}}), which will automatically remove the display: none property (responsible for hiding the element) set by the ng-show directive.
To avoid this, use the ng-style directive, like this:
<div ng-show="activeWindow1" style="border:1px solid black; height:20px;" ng-style="{width: boxWidth}">