I have a need for inheriting scope from a parent controller in a directive. I don't necessarily want to leave scope: false. I also don't necessarily want to use an isolated scope, because it requires a lot of work to get the values I do care about linked properly (think lots of values in a parent controller).
Does it make sense to use scope:true
in my directive if I want to update parent scope?
<div ng-controller="MyCtrl"> Hello, {{name}}! <my-directive></my-directive> </div>
var myApp = angular.module('myApp',[]); //myApp.directive('myDirective', function() {}); //myApp.factory('myService', function() {}); function MyCtrl($scope) { $scope.name = 'Dave'; } myApp.directive('myDirective', function() { return { scope: true, restrict: 'EA', link: function(scope, elem, attrs) { scope.updateName = function(newName) { console.log('newName is: ' + newName); scope.name = newName; } }, template: '<input ng-model="updatedName" placeholder="new name value"> <button ng-click="updateName(updatedName)">Update</button>' } })
Please check out the fiddle
You can still access the parent scope using $parent , but this is not normally recommended. Instead, you should specify which parent scope properties (and/or function) the directive needs via additional attributes on the same element where the directive is used, using the = , @ , and & notation.
Isolate Scope: If the need is to reuse the component (directive) throughout your app, consider creating isolate scopes using scope option. The concept of isolate scope is used to separate the scope inside a directive from the scope outside.
... is quite illustrative as AngularJS doesn't allow multiple directives (on the same DOM level) to create their own isolate scopes. According to the documentation, this restriction is imposed in order to prevent collision or unsupported configuration of the $scope objects.
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.
Although @user1737909 already referenced the SO question to read (What are the nuances of scope prototypal / prototypical inheritance in AngularJS?, which will explain the problem and recommended various ways to fix it), we normally try to give the answer on SO.
So, the reason your fiddle doesn't work is because when a primitive type (i.e., a string, number, or boolean type) is written to -- e.g., scope.name = newName
-- the "write" always goes to the local scope/object. In other words, the child scope gets its own name
property that shadows the parent property of the same name. The fix is to use an object, rather than a primitive type, in the parent scope. The child scope will then get a reference to that object. Any writes to the object properties (whether from the parent or the child) will go to that one object. (The child scope does not get its own object.)
$scope.obj = {name: 'Dave'};
Then in your directive:
scope.obj.name = newName;
and HTML:
Hello, {{obj.name}}!
fiddle
Scope inheritance is not meaning setting the value of a child is setting the value of its parent.
Instead of doing scope.name = newName
on the child scope, add a method to the parent scope, which will do the same job but on the parent scope, and call it from the child scope since the child inherits this method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With