What is the proper way to add event handlers to transclusion content? I do not want the consumers of my directive to add their own click handlers to the document. The directive should handle it. But I'm not sure how I correctly add handlers to the content passed with ng-transclude.
Fiddle around: https://jsfiddle.net/hoe71p0e/12/ (can't get Angular.js and JSFiddle to work; my link function isn't being called)
foo.html
<my-foo>
<button type="button">Foo</button>
</my-foo>
foo.js
return {
template: "<div class='my-foo' data-ng-transclude></div>"
link: function($scope, $elem, $attrs, $ctrl, $transclude) {
$scope.foo = function() {
console.log("this is never called");
};
$transclude(function(clone) {
for (var i in clone) {
if (clone[i].localName === "button") {
angular.element(clone[i]).attr("data-ng-click", "foo()");
}
}
});
}
};
expected result (clicking button should call foo)
<div class="my-foo">
<button type="button" data-ng-click="foo()">Foo</button>
</div>
actual result (clicking button does nothing)
<div class="my-foo">
<button type="button">Foo</button>
</div>
Notice, the data-ng-click
attribute on the button is missing.
Also, I've seen several examples with something like this...
broken.js
$transclude(function(clone) {
angular.element(clone).find("button");
});
...but those fail because .find()
is not coming back with results, even though the inspector seems to think clone contains a "button".
I can't imagine you are even linking in this directive. In you fiddle, you are missing a few basic requirements eg ng-app=""
, restrict: 'E'
(required for 1.2.x) in an element style directive, and transclude: true
. With remediation of those, we get a working example. Furthermore, I'm not sure what you are trying to do with $transclude(function(clone) { /*...*/
, but I suspect this is unnecessary. Observe the following...
<my-foo>
<button type="button" ng-click="foo()">Foo</button>
</my-foo>
.directive('myFoo', function() {
return {
transclude: true,
restrict: 'E',
template: '<div class="my-foo" ng-transclude></div>',
link: function($scope, elem, attrs) {
$scope.foo = function() {
console.log('this is called!');
};
}
};
});
JSFiddle Link - working demo
Per conversation the most straight forward approach you can take to solve this would be leveraging the $compile service and modifying the attribute on your <button>
(once selected) element within your directive link
. Inject $compile
and observe the following...
.directive('myFoo', function($compile) {
return {
transclude: true,
restrict: 'E',
template: '<div class="my-foo" ng-transclude></div>',
link: function($scope, elem, attrs) {
$scope.foo = function() {
console.log('called')
}
var button = elem.find('button');
button.attr('ng-click', 'foo()');
$compile(button)($scope);
}
};
});
JSFiddle Link - $compile
demo
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.