在AngularJS中,如何使一个隔离的范围从ng-repeat的范围继承

时间:2022-01-31 23:44:12

I'm trying to create a custom component that receives arguments in a ng-repeat loop. So for example, say I have a component named "mycomp" that receives a custom argument "name" in a ng-repeat:

我正在尝试创建一个自定义组件,它接收ng-repeat循环中的参数。例如,假设我有一个名为“mycomp”的组件,它在ng-repeat中接收一个自定义参数“name”:

<mycomp 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.

这行不通,因为ng-repeat为它所迭代的每个元素创建一个独立的范围。所以我有了两个层次的作用域。

How do I get around this issue? Am I doing something wrong?

我该如何解决这个问题呢?我做错什么了吗?

Thanks.

谢谢。

1 个解决方案

#1


16  

As I stated in my comment 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):

在模板中,声明要继承的模型,不带{{}(因为使用括号会导致传递的值,而不是对模型本身的引用):

<mycomp 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 comment) 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.

当您创建一个指令时,您可以通过指定范围:true或scope:分别}。

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).

因此,通过创建一个非隔离的范围,所有的父模型都是可用的(您可以访问范围)。obj -通过ng-repeat创建,但也是scope.list)。当然,这很方便,但也很危险(而且并不真正创建可重用的代码)。

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 {{}}!

'@'和'&'都生成一个独立的、未绑定的值(如果您更改,那么只在隔离范围上更改—在您的示例中,原始列表中的对象完全没有更改),惟一的区别是'@'读取一个字符串值,'&'读取一个表达式。这一点很重要:我认为您的代码不能工作的原因是(仅)因为您传递了name="{object .name}"而不是name="{object .name}",因为使用'@'字符串值将被读取,该字符串值可以是obj的名称,但是您必须将其包含在{}中!

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:

如果使用'=',则声明希望该变量与指定的外部变量绑定。因此,如果(在一场疯狂的、疯狂的愤怒中!)你想要在你的指令中有两个以相同的值开始的模型,但是on是绑定的(例如更改被传播到外部范围),你可以这样做:

<mycomp binded-name="obj.name" unbinded-name="{{obj.name}}" ng-repeat="obj in list" />

and in your directive:

和你的指令:

scope:{
  bindedName: "=",
  unbindedName: "@"
}

#1


16  

As I stated in my comment 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):

在模板中,声明要继承的模型,不带{{}(因为使用括号会导致传递的值,而不是对模型本身的引用):

<mycomp 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 comment) 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.

当您创建一个指令时,您可以通过指定范围:true或scope:分别}。

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).

因此,通过创建一个非隔离的范围,所有的父模型都是可用的(您可以访问范围)。obj -通过ng-repeat创建,但也是scope.list)。当然,这很方便,但也很危险(而且并不真正创建可重用的代码)。

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 {{}}!

'@'和'&'都生成一个独立的、未绑定的值(如果您更改,那么只在隔离范围上更改—在您的示例中,原始列表中的对象完全没有更改),惟一的区别是'@'读取一个字符串值,'&'读取一个表达式。这一点很重要:我认为您的代码不能工作的原因是(仅)因为您传递了name="{object .name}"而不是name="{object .name}",因为使用'@'字符串值将被读取,该字符串值可以是obj的名称,但是您必须将其包含在{}中!

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:

如果使用'=',则声明希望该变量与指定的外部变量绑定。因此,如果(在一场疯狂的、疯狂的愤怒中!)你想要在你的指令中有两个以相同的值开始的模型,但是on是绑定的(例如更改被传播到外部范围),你可以这样做:

<mycomp binded-name="obj.name" unbinded-name="{{obj.name}}" ng-repeat="obj in list" />

and in your directive:

和你的指令:

scope:{
  bindedName: "=",
  unbindedName: "@"
}