When defining an ng-repeat directive to iterate over an array, the syntax specifies ng-repeat="friend in friends"
, and then within the template you use the interoplation operator like so {{friend.name}}
.
Is it possible to have the properties assigned to the current item scope, rather than a variable in it? So I could call just {{name}}
instead of {{friend.name}}
?
The reason being is that my directive is being used in the scope of two different templates - for example I might have a directive "userActions"
that is used in both a repeater, and also inside an unrelated template where {{friend.name}}
doesn't make sense. I would like to avoid artificially manufacturing the friend
object where it doesn't have a semantic meaning.
My use case is something like this:
I have a grid that renders blocks of various types. Some psuedo code:
<div ng-repeat="block in blocks">
< cat block />
< friend block >
<userActions directive />
</ friend block >
< guitar block />
.... more blocks
</div>
I also have a friend page, that contains the exact same user actions:
..fragment of friend page..
<element ng-control="friend">
<userActions directive />
</element>
Now, if I want to user a property of the block inside the repeater, the syntax is {{block.name}}
. So the template for userActions
contains this.
However, once I use this template in the friend page, I must create {{block.name}}
inside the scope of the friend controller. This does not make sense though, because the block only exists in the context of the block grid. I shouldn't have to create this block
.
What I want to be able to do, is just to call {{name}}
from within the userActions
directive template, since both the block scope and the controller contain it. I don't want to create a block
object, then artificially set block.name
in each scope where I want to use the userActions
directive.
Here's a jsFiddle to illustrate the cause
It all depends on how you structure your directive. It's hard to tell without a fiddle/plunkr what your code looks like so I'm taking a stab in the dark here. Right now I think what you're trying to say is that in the context of where you're using your directive friend.name does not make sense. Perhaps something more generic like person.name might be more appropriate. In that case you can do the following so that you pass in to the directive what you want the person to be associated with:
Html
javascript
jsfiddle: http://jsfiddle.net/5aVLf/1/
I've decided to combine the informative answers of Mathew Berg and ganaraj with my newfound knowledge to create a helpful answer to this.
The short answer is You really don't want to do that.
The longer answer is this:
When using
ng-repeat="block in blocks
" , a new scope is created for each block element, and the properties of every block object are create inscope.block
of each block. This is a good thing, because this means all properties can be accessed by reference, updated or $watched.If
ng-repeat
wouldn't have done that, and all properties would just be slapped unto the block's scope, then all primitives inblock
(strings, ints, etc) would just be copied from the block object to the block scope object. A change in one will not reflect on the other, and that's bad. More info on that here.Ok so now that we've decided that's a good thing rather than a bad thing, how do we overcome the semantic issue? I've decided to use the
friendData
object container as the object on the scope of my directive, and so the directive expects thefriend-data
attribute to hold the relevant propertiesThis way I can assign this object regardless of which context I'm calling my directive template.
Given these controller contexts:
How to call the directive -
Within an
ng-repeat
:Or in a difference context:
Here's the solution Fiddle
Thanks for all the help!