How to call a method defined in child directive, within a button click listener of parent directive.
angular.module('editableDivDirective', [])
.directive("editableDiv", function() {
var directive = {};
directive.restrict = 'E';
directive.replace = 'true';
directive.scope = {};
directive.transclude = 'true';
directive.template =
'<div id="wrapper">' +
'<div required class="text-area" name="search" contenteditable="true" ng-model="formData.text"></div>' +
'<button type="submit" class="btn btn-warning add-button" id="submit" ng-click="createTodo()">Add</button>' +
'</div>';
directive.link = function(scope, element, attrs, controller) {
scope.createTodo = function(){
// do something
// Call child directive setPlaceholderText()
}
};
return directive;
})
.directive("contenteditable", function() {
var directive = {};
directive.require = ['^editableDiv','?ngModel'];
directive.restrict = 'A';
directive.scope = {};
directive.link = function(scope, element, attrs, ctrls) {
var ngModel = ctrls[1];
var editableDivController = ctrls[0];
function setPlaceholderText(){
return element.html("Hello World");
}
return directive;
})
I want to call child directive setPlaceholderText() when 'scope.createTodo()' of parent directive is called.
How can that be done.
In your parent directive
link: function($scope,$el,$attr) {
$el.find(".thing").on('click',function(event){
$scope.$broadcast('thing', $scope.someData);
});
}
In your child directive
link: function($scope. $el, $attr) {
$scope.$on('thing',function(event, someData) {
alert('My parent called me with this data: ' + someData);
});
}
You can $broadcast an event to child scopes (as mentioned), or you can also add a function to your parent directive's controller from your child directive.
Here is a jsfiddle with examples of both $broadcast to child directive and using the controller technique.
angular.module("myApp", [])
.directive("parentDirective", function () {
var directive = {};
directive.restrict = "E";
directive.scope = {};
directive.template = '<div>' +
'<button type="button" ng-click="broadcastDemo()">' +
'Broadcast to child' +
'</button>' +
'<button type="button" ng-click="controllerDemo()">' +
'Use Controller' +
'</button><br /><br />' +
'<child-directive></child-directive>';
//Setup directive controller
directive.controller = function ($scope) {
var ctrl = this;
//Store events for convenience
var events = ctrl.events = {
setPlaceHolderText: "setPlaceHolderTextEvent"
};
$scope.broadcastDemo = function () {
//$broadcast event and optional additional args
$scope.$broadcast(events.setPlaceHolderText, "Additional arg1", "Additional arg2");
};
$scope.controllerDemo = function () {
//do some work
//call the ctrl.setPlaceHolderText added by child
if (ctrl.setPlaceHolderText) {
ctrl.setPlaceHolderText();
}
};
};
return directive;
})
.directive("childDirective", function () {
var directive = {};
directive.restrict = "E";
directive.scope = {};
directive.require = ["^parentDirective", "?ngModel"];
directive.template = '<div></div>';
directive.link = function (scope, elem, attrs, ctrl) {
var parentDirCtrl = ctrl[0];
//allow parent scope(s) to $broadcast event
scope.$on(parentDirCtrl.events.setPlaceHolderText,
function (event, arg1, arg2) {
elem.html("$Broadcast: " + arg1 + " " + arg2);
});
//Add function to parent controller
parentDirCtrl.setPlaceHolderText = function () {
elem.html("Added to parent controller!");
}
};
return directive;
});
If you have multiple childDirectives and you go with adding function to parent directive controller, you will have to take precaution because each additional child directive would clobber the ctrl.setPlaceHolderText (i.e. only one elem.html would be called).
The bindonce library uses something similar to the second technique to allow child directives to add "binders" to the parent directive. The eventing model is probably cleaner for your purposes, but wanted to provide another option for directive communication.
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