Let's say I've got a directive that looks like this:
directive('attachment', function() {
return {
restrict: 'E',
controller: 'AttachmentCtrl'
}
})
That means I can write a list of 'attachment' elements like this:
<attachment ng-repeat="a in note.getAttachments()">
<p>Attachment ID: {{a.id}}</p>
</attachment>
In the above snippet, let's assume that note.getAttachments()
returns a set of simple javascript object hashes.
Since I set a controller for the directive, I can include calls to that controller's scope functions inline.
Here's the controller:
function AttachmentCtrl($scope) {
$scope.getFilename = function() {
return 'image.jpg';
}
}
And here is the modified HTML for when we include a call to that $scope.getFilename
function inline (the new 2nd paragraph):
<attachment ng-repeat="a in note.getAttachments()">
<p>Attachment ID: {{a.id}}</p>
<p>Attachment file name: {{getFilename()}}
</attachment>
However, this isn't useful. This will just print the same string, "image.jpg", as the file name for each attachment.
In actuality, the file name for the attachments is based on attachment ID. So an attachment with ID of "2" would have the file name of "image-2.jpg".
So our getFilename
function needs to be modified. Let's fix it:
function AttachmentCtrl($scope) {
$scope.getFilename = function() {
return 'image-' + a.id + '.jpg';
}
}
But wait — this won't work. There is no variable a
in the scope. We can use the variable a
inline thanks to the ng-repeat
, but that a
variable isn't available to the scope bound to the directive.
So the question is, how do I make that a
available to the scope?
Please note: I realize that in this particular example, I could just print image-{{a.id}}.jpg
inline. But that does not answer the question. This is just an extremely simplified example. In reality, the getFilename
function would be something too complex to print inline.
Edit: Yes, getFilename
can accept an argument, and that would work. However, that also does not answer the question. I still want to know, without workarounds, whether you can get a
into the scope without using it inline.
For example, maybe there is a way to inject it directly into the controller so it would be written as:
function AttachmentCtrl($scope, a) { ... }
But where would I pass it in from? Is there something I can add to the directive declaration? Maybe an ng-* attribute I can add next to the ng-repeat? I just want to know if it's possible.
But wait — this won't work. There is no variable "a" in the scope. We can use the variable a inline thanks to the ng-repeat, but that a variable isn't available to the scope bound to the directive.
Actually variable a
is in the scope associated with the directive controller. Each controller created by the directive gets the child scope created by the ng-repeat iteration. So this works (note $scope.a.id):
function AttachmentCtrl($scope) {
$scope.getFilename = function() {
return 'image-' + $scope.a.id + '.jpg';
}
Here's a fiddle that shows the controller scope, directive scopes, and ngRepeat scopes.
"If multiple directives on the same element request new scope, only one new scope is created. " -- Directive docs, section "Directive Definition Object"
In your example, ng-repeat is creating a new scope, so all directives on that same element get that same new (child) scope.
Also, if you do ever come across a case where you need to get a variable into a controller, using attributes would be better than using ng-init.
Another way would be to use ng-init
and set a model property for child scope. See this fiddle
Relevant code would be
<div ng-app='myApp' ng-controller='MyCtrl'>
<attachment ng-repeat="a in attachments" ng-init='model=a'>
<p>Attachment ID: {{model.id}}</p>
<p>Attachment file name: {{getFilename()}}</p>
</attachment>
</div>
and
function AttachmentCtrl($scope) {
$scope.getFilename = function () {
return 'image-' + $scope.model.id + '.jpg';
}
}
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