In AngularJS, I have directive with basic transclusion. I know that usually is transcluded input or textarea when i using it, and if is there, I want to $watch its model for changes. But I don't have access to attribs of transcluded content, only access to attribs of root element which directive is called on. Transcluded scope as well (maybe scope.$$nextSibling can help but something tells me that it's way to hell :) ).
So is there any way to do that without adding another parameter (attribute) to element where is directive called?
directive template
<div ng-transclude>
<someContent>...</someContent>
<!-- HERE IS INPUT TRANSCLUDED -->
</div>
directive usage
<div my-directive="somedata"> //this attribs are accessable
<input ng-model="iWantToWatchThisInMyDirective" /> //but i want to access this also
</div>
Here is my solution:
I created second directive: Input (restricted for Element, so every input has one). In Input directive I broadcast every change to element's scope:
link: function (scope, element: JQuery, attrs: ng.IAttributes) {
if(typeof attrs.ngModel !== "undefined") {
scope.$watch(attrs.ngModel, function (newValue, oldValue) {
scope.$broadcast('valueChanged'+scope.$id, newValue, oldValue);
});
}
}
scope.$id is used just for be sure that event name is unique for every input.
Now, in any other directive I can listen event of changing any input:
link: function (scope, element:JQuery, attrs:ng.IAttributes) {
//My input is last child everytime..
var children = element.find("input");
var lastInput = angular.element(children[children.length - 1]);
var lastInputScope = lastInput.scope();
var unregister = lastInputScope.$on('valueChanged' + lastInputScope.$id,
function (event, newValue, oldValue) {
//do whatever you want...
});
scope.$on('$destroy', function () {
unregister();
});
}