AngularJS - accessing parent directive properties from child directives
Solution 1
Taking inspiration from this SO post, I've got a working solution here in this plunker.
I had to change quite a bit. I opted to have an isolated scope on the editableString
as well because it was easier to bind in the correct values to the template. Otherwise, you are going to have to use compile
or another method (like $transclude
service).
Here is the result:
JS:
var myApp = angular.module('myApp', []);
myApp.controller('Ctrl', function($scope) {
$scope.myModel = { property1: 'hello1', property2: 'hello2' }
});
myApp.directive('editableFieldset', function () {
return {
restrict: 'E',
scope: {
model: '='
},
transclude: true,
replace: true,
template: '<div class="editable-fieldset" ng-click="edit()"><div ng-transclude></div></div>',
link: function(scope, element) {
scope.edit = function() {
scope.editing = true;
}
},
controller: ['$scope', function($scope) {
this.getModel = function() {
return $scope.model;
}
}]
};
});
myApp.directive('editableString', function () {
return {
restrict: 'E',
replace: true,
scope: {
label: '@',
field: '@'
},
template: '<div><label>{{ label }}</label><p>{{ model[field] }}</p></div>',
require: '^editableFieldset',
link: function(scope, element, attrs, ctrl) {
scope.model = ctrl.getModel();
}
};
});
HTML:
<body ng-controller="Ctrl">
<h1>Hello Plunker!</h1>
<editable-fieldset model="myModel">
<editable-string label="Some Property1:" field="property1"></editable-string>
<editable-string label="Some Property2:" field="property2"></editable-string>
</editable-fieldset>
</body>
Solution 2
You can get access to parent controller by passing attribute in child directive link function
link: function (scope, element, attrs, parentCtrl) {
parentCtrl.$scope.editing = true;
}
Related videos on Youtube
Rahul Sekhar
Updated on June 14, 2022Comments
-
Rahul Sekhar about 2 years
This should not be too hard a thing to do but I cannot figure out how best to do it.
I have a parent directive, like so:
directive('editableFieldset', function () { return { restrict: 'E', scope: { model: '=' }, replace: true, transclude: true, template: ' <div class="editable-fieldset" ng-click="edit()"> <div ng-transclude></div> ... </div>', controller: ['$scope', function ($scope) { $scope.edit = -> $scope.editing = true // ... ] }; });
And a child directive:
.directive('editableString', function () { return { restrict: 'E', replace: true, template: function (element, attrs) { '<div> <label>' + attrs.label + '</label> <p>{{ model.' + attrs.field + ' }}</p> ... </div>' }, require: '^editableFieldset' }; });
How can I easily access the
model
andediting
properties of the parent directive from the child directive? In my link function I have access to the parent scope - should I use$watch
to watch these properties?Put together, what I'd like to have is:
<editable-fieldset model="myModel"> <editable-string label="Some Property" field="property"></editable-string> <editable-string label="Some Property" field="property"></editable-string> </editable-fieldset>
The idea is to have a set of fields displayed by default. If clicked on, they become inputs and can be edited.
-
Rahul Sekhar over 10 yearsThank you. This doesn't really help to access a dynamic property, like
editing
though. I guess I would have to use$watch
to keep track of that in my child directive? -
Rahul Sekhar over 10 yearsAlso, I would think for constant, unchanging attributes like
field
andlabel
here, passing them to a function that generates the template would be faster than adding them as bindings? There's no need to waste time on each digest cycle checking for those bindings that won't change, right? -
Davin Tryon over 10 yearsIsn't editing a property of the child? Or do you want to only edit one child at a time?
-
Rahul Sekhar over 10 yearsI'd like to edit all children at a time. Editing is a property of the parent that I'd like the children to be able to read and change their state depending on its value.
-
Davin Tryon over 10 yearsYes, some sort of
$watch
in the child. Probably exposed through the parent controller. -
Leonardo over 10 yearsyou get this fourth param if you: ... require: "^parentCtrl"
-
Harish about 9 yearsYes and the concept is explained in the section "Creating Directives that Communicate" in the documentation for directives link