I'm trying to create a custom ponent that receives arguments in a ng-repeat loop. So for example, say I have a ponent named "myp" that receives a custom argument "name" in a ng-repeat:
<myp name="{obj.name}" ng-repeat="obj in list" />
And in my directive the isolated scope is defined like this:
scope:{name:"@"}
That won't work because ng-repeat creates an isolated scope for each element it iterates. So I ended up having two levels of scopes.
How do I get around this issue? Am I doing something wrong?
Thanks.
I'm trying to create a custom ponent that receives arguments in a ng-repeat loop. So for example, say I have a ponent named "myp" that receives a custom argument "name" in a ng-repeat:
<myp name="{obj.name}" ng-repeat="obj in list" />
And in my directive the isolated scope is defined like this:
scope:{name:"@"}
That won't work because ng-repeat creates an isolated scope for each element it iterates. So I ended up having two levels of scopes.
How do I get around this issue? Am I doing something wrong?
Thanks.
Share Improve this question edited Oct 3, 2013 at 19:12 yohairosen asked Nov 19, 2012 at 8:09 yohairosenyohairosen 1,6851 gold badge18 silver badges26 bronze badges 2- Already answered here: stackoverflow./questions/13294507/… – Tiago Roldão Commented Nov 19, 2012 at 10:28
- We need more code. It's hard to tell what you're trying to do here. – Ben Lesh Commented Nov 19, 2012 at 14:27
1 Answer
Reset to default 16As I stated in my ment of your original question, this has already been answered. Anyway, here it is, summed up:
In your template, state the model you want to have inherited, without {{}} (as using brackets results in the value being passed, and not the reference to the model itself):
<myp name="obj.name" ng-repeat="obj in list" />
And in your directive, establish a 2-way binding, like so:
scope:{name:"="}
EDIT:
I realize now (after your ment) that while this solves your problem, it doesn't fully answer the question. Here goes:
When you create a directive you have the choice of creating a scope that inherits from its parent (controller, typically, though not necessarily) ou an "isolated" scope, by specifying scope: true
or scope: {...}
, respectively.
So, by creating an unisolated scope, all the parent's models are available (you can access scope.obj - created via ng-repeat - but also scope.list). This is convenient, but also dangerous, of course (and doesn't really create reusable code).
If you create an isolated scope, you can specify the scope's models using '@', '=' or '&'.
'@' and '&' both produce a isolated, unbinded value, (that, if you change, changes only on the isolated scope - in your case, the object in the original list suffers no change at all), the only difference being that '@' reads a string value, and '&' reads an expression.
THIS IS IMPORTANT: the reason why I believe your code didn't work was (only) because you passed name="{obj.name}"
and not name="{{obj.name}}"
, for with '@' the string value is read, and that string value can be the name of obj, but you must include it in {{}}!
If you use '=', you are declaring that you want that variable to be binded with the specified outside variable. So, if (in a fit of crazy, crazy rage!) you want to have 2 models in your directive that start up with the same value, but on is binded (i.e. changes are propagated to the outside scope), you could do something like this:
<myp binded-name="obj.name" unbinded-name="{{obj.name}}" ng-repeat="obj in list" />
and in your directive:
scope:{
bindedName: "=",
unbindedName: "@"
}