Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angularjs watch for change in parent scope

I'm writing a directive and I need to watch the parent scope for a change. Not sure if I'm doing this the preferred way, but its not working with the following code:

  scope.$watch(scope.$parent.data.overlaytype,function() {     console.log("Change Detected...");   }) 

This it logged on window load, but never again, even when overlaytype is changed.

How can I watch overlaytype for a change?

Edit: here is the entire Directive. Not entirely sure why I'm getting a child scope

/* Center overlays vertically directive */ aw.directive('center',function($window){   return {     restrict : "A",     link : function(scope,elem,attrs){        var resize = function() {         var winHeight = $window.innerHeight - 90,             overlayHeight = elem[0].offsetHeight,             diff = (winHeight - overlayHeight) / 2;             elem.css('top',diff+"px");       };        var watchForChange = function() {         return scope.$parent.data.overlaytype;       }       scope.$watch(watchForChange,function() {         $window.setTimeout(function() {           resize();         }, 1);       })        angular.element($window).bind('resize',function(e){         console.log(scope.$parent.data.overlaytype)         resize();       });     }   }; }); 
like image 735
wesbos Avatar asked Jul 24 '13 15:07

wesbos


People also ask

How are apply () Watch () Digest () different in AngularJS?

$apply() function will execute custom code and then it will call $scope. $digest() function forcefully to check all watch list variables and update variable values in view if any changes found for watch list variables. In most of the time angularjs will use $scope.

What is scope watch in AngularJS?

When you create a data binding from somewhere in your view to a variable on the $scope object, AngularJS creates a "watch" internally. A watch means that AngularJS watches changes in the variable on the $scope object. The framework is "watching" the variable. Watches are created using the $scope.

Does AngularJS support scope inheritance?

The $scope object used by views in AngularJS are organized into a hierarchy. There is a root scope, and the $rootScope can has one or more child scopes.

What is parent scope in AngularJS?

Angular scopes include a variable called $parent (i.e. $scope. $parent ) that refer to the parent scope of a controller. If a controller is at the root of the application, the parent would be the root scope ( $rootScope ). Child controllers can therefore modify the parent scope since they access to it.

How to watch changes in $scope in AngularJS?

In angularjs $watch () function is used to watch the changes of variables in $scope object. Generally the $watch () function will create internally in angularjs to handle variable changes in application.

What is the use of $watch in AngularJS?

In angularjs $watch() function is used to watch the changes of variables in $scope object. Generally the $watch() function will create internally in angularjs to handle variable changes in application. Suppose in our angularjs applications if we want to create custom watch for some actions then it’s better to use $scope.watch function.

How to remove the parent scope from the scope hierarchy?

The parent scope will propagate the $digest()event. The scope can be removed from the scope hierarchy using $destroy(). $destroy()must be called on a scope when it is desired for the scope and its child scopes to be permanently detached from the parent and thus stop participating in model change detection and listener notification by invoking.

How do you create a child scope in HTML?

Child scopes are created using the $new()method. (Most scopes are created automatically when compiled HTML template is executed.) See also the Scopes guidefor an in-depth introduction and usage examples. Inheritance A scope can inherit from a parent scope, as in this example:


2 Answers

If you want to watch a property of a parent scope you can use $watch method from the parent scope.

//intead of $scope.$watch(...) $scope.$parent.$watch('property', function(value){/* ... */}); 

EDIT 2016: The above should work just fine, but it's not really a clean design. Try to use a directive or a component instead and declare its dependencies as bindings. This should lead to better performance and cleaner design.

like image 136
Petr Peller Avatar answered Sep 22 '22 09:09

Petr Peller


I would suggest you to use the $broadcast between controller to perform this, which seems to be more the angular way of communication between parent/child controllers

The concept is simple, you watch the value in the parent controller, then, when a modification occurs, you can broadcast it and catch it in the child controller

Here's a fiddle demonstrating it : http://jsfiddle.net/DotDotDot/f733J/

The part in the parent controller looks like that :

$scope.$watch('overlaytype', function(newVal, oldVal){     if(newVal!=oldVal)         $scope.$broadcast('overlaychange',{"val":newVal}) }); 

and in the child controller :

$scope.$on('overlaychange', function(event, args){     console.log("change detected")     //any other action can be perfomed here }); 

Good point with this solution, if you want to watch the modification in another child controller, you can just catch the same event

Have fun

Edit : I didn't see you last edit, but my solution works also for the directive, I updated the previous fiddle ( http://jsfiddle.net/DotDotDot/f733J/1/ )

I modified your directive to force it to create a child scope and create a controller :

directive('center',function($window){   return {     restrict : "A",     scope:true,     controller:function($scope){         $scope.overlayChanged={"isChanged":"No","value":""};         $scope.$on('overlaychange', function(event, args){         console.log("change detected")         //whatever you need to do      });   }, link : function(scope,elem,attrs){    var resize = function() {     var winHeight = $window.innerHeight - 90,         overlayHeight = elem[0].offsetHeight,         diff = (winHeight - overlayHeight) / 2;         elem.css('top',diff+"px");   };   angular.element($window).bind('resize',function(e){     console.log(scope.$parent.data.overlaytype)     resize();       });     }   }; }); 
like image 20
DotDotDot Avatar answered Sep 19 '22 09:09

DotDotDot