AngularJS directive watch parent size change

el n00b picture el n00b · Mar 27, 2015 · Viewed 12.2k times · Source

Problem

I have a simple directive that executes sizing updates on a particular element. This watches the window size and makes adjustments accordingly.

MyApp.directive('resizeTest', ['$window', function($window) {
  return {
    restrict: 'AC',
    link: function(scope, element) {
      var w = angular.element($window);
      scope.$watch(function() {
        return { 'h': w.height(), 'w': w.width() };
      }, function(newValue, oldValue) {
        // resizing happens here
      }, true);
      w.bind('resize', function() { scope.$apply(); });
    }
  };
}]);

This works just fine.

It just so happens that inside of the div tag that is associated with, I have a child div. When the parent is resized, I want to make positioning alterations on the child element. However, I cannot get the trigger to fire.

This gets called at startup, but does not get triggered when the element is resized or the window changes:

MyApp.directive('centerVertical', ['$window', function($window) {
  return {
    restrict: 'AC',
    link: function(scope, element) {
      element.css({border: '1px solid #0000FF'});
      scope.$watch('data.overlaytype', function() {
        $window.setTimeout(function() {
          console.log('I am:      ' + element.width() + 'x' + element.height());
          console.log('Parent is: ' + element.parent().width() + 'x' + element.parent().height());
        }, 1);
      });
    }
  };
}]);

What type of binding or watch configuration should I be using to check for resizing of the parent element?

Fiddle

https://jsfiddle.net/rcy63v7t/1/

Answer

jcz picture jcz · Mar 27, 2015

The value data.overlaytype you are observing in the centerVertical directive is not on the scope so the resulting value is undefined and this value never changes that's why you dont get the listener executed. To check if the size of the parent element changed you can check it in the $watch function like this:

scope.$watch(
    function () { 
        return {
           width: element.parent().width(),
           height: element.parent().height(),
        }
   },
   function () {}, //listener 
   true //deep watch
);

Moreover remember, when you want to use an already existing module you can't call it like this angular.module('myModule', []) because this mean creating new module. You have to just pass the module name angular.module('myModule'), which is second thing why your code didn't work.