Javascript 将范围传递给 ng-include
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25678560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular passing scope to ng-include
提问by kbjr
I have a controller that I wrote that I use in multiple places in my app with ng-includeand ng-repeat, like this:
我有一个我写的控制器,我在我的应用程序的多个地方使用ng-includeand ng-repeat,如下所示:
<div
ng-repeat="item in items"
ng-include="'item.html'"
ng-controller="ItemController"
></div>
In the controller/template, I expect the itemvalue to exist, and the whole thing is built around this idea. Now, though, I need to use the controller in a slightly different way, without the ng-repeat, but still need to be able to pass in an item. I saw ng-initand thought it could do what I needed, like this:
在控制器/模板中,我希望item值存在,并且整个事情都是围绕这个想法构建的。现在,虽然,我需要以稍微不同的方式使用控制器,没有ng-repeat,但仍然需要能够传递item. 我看到ng-init并认为它可以做我需要的,像这样:
<div
ng-init="item = leftItem"
ng-include="'item.html'"
ng-controller="ItemController"
></div>
<div
ng-init="item = rightItem"
ng-include="'item.html'"
ng-controller="ItemController"
></div>
But that does not seem to be working. Anyone have any ideas how I can pass in a variable for scope in a singular instance like this?
但这似乎不起作用。任何人都知道如何在像这样的单一实例中传入作用域变量?
Edit:
The controller above this is loading in the leftItemand rightItemvalues, something like this:
编辑:上面的控制器正在加载leftItem和rightItem值,如下所示:
.controller('MainController', function($scope, ItemModel) {
ItemModel.loadItems()
.then(function(items) {
$scope.$apply(function() {
$scope.leftItem = items.left;
$scope.rightItem = items.right;
});
});
});
采纳答案by kbjr
I ended up rewriting it into a directive and binding the needed value in the scope with
我最终将它重写为一个指令,并在范围内绑定所需的值
scope: {
item: '='
}
回答by Piou
Late to the party, but there is a little angular 'hack' to achieve this without implementing a dumb directive.
晚会晚了,但是有一个小角度的“黑客”可以在不执行愚蠢指令的情况下实现这一点。
Adding a built-in directive that will extend your controller's scope (like ng-if) everywhere you use the ng-include will actually let you isolate the variable name for all the included scopes.
添加一个内置指令,该指令将在您使用 ng-include 的任何地方扩展您的控制器的范围(如 ng-if)实际上会让您隔离所有包含范围的变量名称。
So:
所以:
<div ng-include="'item.html'"
ng-if="true"
onload="item = rightItem">
</div>
<div ng-include="'item.html'"
ng-if="true"
onload="item = leftItem">
</div>
You can then bind your template item.html to the item variable several times with different items.
然后,您可以使用不同的项目多次将模板 item.html 绑定到项目变量。
Here is a plunker to achieve what you want
The problem was the item keeps changing in the controller scope that only holds one reference to item variable which is erased at each onload instruction.
问题是该项目在控制器范围内不断变化,该控制器范围内只保存一个对项目变量的引用,该引用在每个加载指令中被擦除。
Introducing a directive that extends the current scope, lets you have a isolated scope for all the ng-include. As a consequence the item reference is preserved and unique in all extended scope.
引入一个扩展当前作用域的指令,让您拥有所有 ng-include 的独立作用域。因此,项目引用在所有扩展范围内被保留且唯一。
回答by Sunil D.
You can use the onloadattribute that ngIncludeprovides to do this:
您可以使用提供的onload属性ngInclude来执行此操作:
<div ng-include="'item.html'"
ng-controller="ItemController"
onload="item = rightItem">
</div>
EDIT
编辑
Try doing something like this in the parent scope:
尝试在父作用域中做这样的事情:
$scope.dataHolder = {};
Then when the asynchronous data is received, store the data on dataHolder:
然后当接收到异步数据时,将数据存储在dataHolder:
$scope.dataHolder.leftItem = items.leftItem;
$scope.dataHolder.rightItem = items.rightItem;
Now when ng-includeloads the template, it will create a child scope that inherits the properties of the parent. So $scope.dataHolderwill be defined in this child scope (initially as an empty object). But when your asynchronous data is received, the reference to the empty object should then contain the newly received data.
现在,当ng-include加载模板时,它将创建一个继承父级属性的子级作用域。So$scope.dataHolder将在这个子作用域中定义(最初作为一个空对象)。但是当接收到异步数据时,对空对象的引用应该包含新接收的数据。
回答by Mike
LOVE @Tanin's answer. solves somany problems at once and in a very elegant way. For those of you like me who don't know Coffeescript, here's the javascript...
喜欢@Tanin 的回答。以非常优雅的方式同时解决这么多问题。对于像我这样不了解 Coffeescript 的人,这里是 javascript...
NOTE: For reasons I'm too new to understand, this code requires you to quote your template name once, rather than ng-include's requirement to twice-quote your template names, ie. <div ng-include-template="template-name.html" ... >instead of <div ng-include-template="'template-name.html'" ... >
注意:由于我太新而无法理解的原因,此代码要求您引用模板名称一次,而不是 ng-include 要求两次引用模板名称,即。<div ng-include-template="template-name.html" ... >代替<div ng-include-template="'template-name.html'" ... >
.directive('ngIncludeTemplate', function() {
return {
templateUrl: function(elem, attrs) { return attrs.ngIncludeTemplate; },
restrict: 'A',
scope: {
'ngIncludeVariables': '&'
},
link: function(scope, elem, attrs) {
var vars = scope.ngIncludeVariables();
Object.keys(vars).forEach(function(key) {
scope[key] = vars[key];
});
}
}
})
回答by Tanin
Using onload is not a clean solution because it litters the global scope. If you have something more complex, it'll start to fail.
使用 onload 不是一个干净的解决方案,因为它会影响全局范围。如果你有更复杂的东西,它就会开始失败。
ng-include is not that reusable because it has access to the global scope. It's a little weird.
ng-include 不是可重用的,因为它可以访问全局范围。这有点奇怪。
The above is not true. ng-if with onload doesn't litter the global scope
以上是不正确的。带有 onload 的 ng-if 不会影响全局范围
We also don't want to write a specific directive for every situation.
我们也不想为每种情况编写特定的指令。
Making a generic directive instead of ng-include is a cleaner solution.
制作一个通用指令而不是 ng-include 是一个更简洁的解决方案。
The ideal usage looks like:
理想的用法如下:
<div ng-include-template="'item.html'" ng-include-variables="{ item: 'whatever' }"></div>
<div ng-include-template="'item.html'" ng-include-variables="{ item: variableWorksToo }"></div>
The directive is:
该指令是:
.directive(
'ngIncludeTemplate'
() ->
{
templateUrl: (elem, attrs) -> attrs.ngIncludeTemplate
restrict: 'A'
scope: {
'ngIncludeVariables': '&'
}
link: (scope, elem, attrs) ->
vars = scope.ngIncludeVariables()
for key, value of vars
scope[key] = value
}
)
You can see that the directive doesn't use the global scope. Instead, it reads the object from ng-include-variables and add those members to its own local scope.
您可以看到该指令不使用全局范围。相反,它从 ng-include-variables 读取对象并将这些成员添加到它自己的本地范围。
I hope this is what you would like; it's clean and generic.
我希望这是你想要的;它干净而通用。
回答by Will Sadler
ng-init is better for this I think.
我认为 ng-init 对此更好。
<div ng-include='myFile.html' ng-init="myObject = myCtrl.myObject; myOtherObject=myCtrl.myOtherObject"/>
回答by Viktor Aseev
Above will not work for second level attributes, like <div ng-include-template=... ng-include-variables="{ id: var.id }">. Notice the var.id.
以上不适用于二级属性,例如<div ng-include-template=... ng-include-variables="{ id: var.id }">. 请注意var.id.
Updated directive(ugly, but works):
更新指令(丑陋,但有效):
.directive('ngIncludeTemplate', function() {
return {
templateUrl: function(elem, attrs) { return attrs.ngIncludeTemplate; },
restrict: 'A',
scope: {
'ngIncludeVariables': '&'
},
link: function(scope, elem, attrs) {
var cache = scope.ngIncludeVariables();
Object.keys(cache).forEach(function(key) {
scope[key] = cache[key];
});
scope.$watch(
function() {
var val = scope.ngIncludeVariables();
if (angular.equals(val, cache)) {
return cache;
}
cache = val;
return val;
},
function(newValue, oldValue) {
if (!angular.equals(newValue, oldValue)) {
Object.keys(newValue).forEach(function(key) {
scope[key] = newValue[key];
});
}
}
);
}
};
});
回答by Zmey Petrov
Maybe obvious update for Mike and Tanin answers - if you using inline templates as:
Mike 和 Tanin 的答案可能有明显的更新 - 如果您使用内联模板作为:
<script type="text/ng-template" id="partial">{{variable}}</script>
<div ng-include-template="'partial'" ng-include-variables="{variable: variable}"></div>
Then, in directive ngIncludeTemplate, replace
然后,在指令 ngIncludeTemplate 中,替换
templateUrl: function(elem, attrs) { return attrs.ngIncludeTemplate; },
With
和
template: function(elem, attrs) { return document.getElementById(attrs.ngIncludeTemplate.split("'")[1]).innerHTML },

