ChaseLouisPowers
ChaseLouisPowers

Reputation: 755

ng-style Variable Not Updating When Scope is Updated

I'm monitoring a CSS style and updating a variable in the scope that's based on that CSS style's value. It works the first time around but when the browser is resized, the scope gets updated but ng-style does not update with the new scope parameter.

JS:

.directive('monitorStyle', function() {
        return {
            link: function(scope, element, attrs) {
                scope[attrs.updateVariable] = $(element).css(attrs.monitorStyle);
                angular.element(window).on('resize', function() {
                    scope[attrs.updateVariable] = $(element).css(attrs.monitorStyle);
                });

            }
        }
    })

HTML:

<p class="text" monitor-style="font-size" update-variable="textHeight">Press "<img class="mini up" src="img/select-arrow.png" src="Up" ng-style="{'height': textHeight}">

I'm trying to do this outside of the controller because that's what people recommend. Why is ng-style not updating when the scope gets updated?

Upvotes: 1

Views: 3954

Answers (2)

ChaseLouisPowers
ChaseLouisPowers

Reputation: 755

Yo, I made this sick solution.

So if you want to watch styles (even an array of them on a particular element) and then send their values to the $scope you can use this JS:

.directive('monitorStyle', function($timeout) {
    return {
        link: function(scope, element, attrs) {
            function addToScope() {
                var updateVariable = attrs.updateVariable.split(',');
                var monitorStyle = attrs.monitorStyle.split(',');
                for (var i = 0; i < updateVariable.length; i++) {
                    scope[updateVariable[i]] = $(element).css(monitorStyle[i]);
                }
            }
            addToScope();
            angular.element(window).on('resize', function() {
                addToScope();
                scope.$apply();
            });
        }
    }
})

And apply it like this:

<h2 monitor-style="font-size,line-height" update-variable="headerHeight,headerLineHeight">

This will update the $scope on initialization and on window resizes. You can of course modify it to your own purpose.

Each time the $scope changes you can update other styles like this:

<div ng-style="{'height': headerHeight, 'line-height': headerLineHeight}">

Upvotes: 0

Damien
Damien

Reputation: 4093

The window event isn't an angular event, so angular don't know he have to update the model/scope. You have to add scope.$apply() to tell angular to refresh it :

angular.element(window).on('resize', function() {
    scope[attrs.updateVariable] = $(element).css(attrs.monitorStyle);
    scope.$apply();
});

Data bindig only works when your model is updated with angular event like $http, $timeout, ng-click, ...

A great article about it : http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

Upvotes: 4

Related Questions