角度传递范围到ng-include
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了角度传递范围到ng-include相关的知识,希望对你有一定的参考价值。
我有一个控制器,我用ng-include
和ng-repeat
在我的应用程序的多个地方使用,如下所示:
<div
ng-repeat="item in items"
ng-include="'item.html'"
ng-controller="ItemController"
></div>
在控制器/模板中,我希望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>
但这似乎并没有奏效。任何人都有任何想法如何在像这样的单一实例中传入变量的范围?
编辑:上面的控制器加载leftItem
和rightItem
值,如下所示:
.controller('MainController', function($scope, ItemModel) {
ItemModel.loadItems()
.then(function(items) {
$scope.$apply(function() {
$scope.leftItem = items.left;
$scope.rightItem = items.right;
});
});
});
您可以使用onload
提供的ngInclude
属性来执行此操作:
<div ng-include="'item.html'"
ng-controller="ItemController"
onload="item = rightItem">
</div>
编辑
尝试在父作用域中执行以下操作:
$scope.dataHolder = {};
然后,当收到异步数据时,将数据存储在dataHolder
上:
$scope.dataHolder.leftItem = items.leftItem;
$scope.dataHolder.rightItem = items.rightItem;
现在,当ng-include
加载模板时,它将创建一个继承父项属性的子作用域。因此,$scope.dataHolder
将在此子范围中定义(最初作为空对象)。但是当收到异步数据时,对空对象的引用应该包含新接收的数据。
晚到派对,但有一个有点角度'黑客'来实现这一点,而不实施一个愚蠢的指令。
添加一个内置指令,可以扩展控制器的范围(如ng-if),无论你在哪里使用ng-include,实际上都可以让你为所有包含的范围隔离变量名。
所以:
<div ng-include="'item.html'"
ng-if="true"
onload="item = rightItem">
</div>
<div ng-include="'item.html'"
ng-if="true"
onload="item = leftItem">
</div>
然后,您可以使用不同的项目将模板item.html多次绑定到项目变量。
Here is a plunker to achieve what you want
问题是项目在控制器范围内不断变化,只保存对每个onload指令中擦除的项目变量的一个引用。
通过引入扩展当前范围的指令,您可以为所有ng-include设置一个独立的范围。因此,项目引用在所有扩展范围内都保留并且是唯一的。
我最终将它重写为一个指令并将范围内的所需值绑定到
scope: {
item: '='
}
爱@ Tanin的回答。以一种非常优雅的方式同时解决了很多问题。对于那些不喜欢Coffeescript的我喜欢的人,这里是javascript ...
注意:由于我太难理解的原因,此代码要求您引用模板名称一次,而不是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];
});
}
}
})
使用onload并不是一个干净的解决方案,因为它会影响全局范围。如果你有更复杂的东西,它将开始失败。
ng-include不是可重用的,因为它可以访问全局范围。这有点奇怪。
以上情况并非如此。 ng-if with onload不会乱丢全局范围
我们也不想为每种情况编写特定的指令。
制定通用指令而不是ng-include是一种更清晰的解决方案。
理想的用法如下:
<div ng-include-template="'item.html'" ng-include-variables="{ item: 'whatever' }"></div>
<div ng-include-template="'item.html'" ng-include-variables="{ item: variableWorksToo }"></div>
该指令是:
.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
}
)
您可以看到该指令不使用全局范围。相反,它从ng-include-variables读取对象并将这些成员添加到其自己的本地范围。
我希望这是你想要的;它干净而且通用。
我认为ng-init对此更好。
<div ng-include='myFile.html' ng-init="myObject = myCtrl.myObject; myOtherObject=myCtrl.myOtherObject"/>
以上不适用于二级属性,如<div ng-include-template=... ng-include-variables="{ id: var.id }">
。注意var.id
。
更新指令(丑陋,但有效):
.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];
});
}
}
);
}
};
});
对于Mike和Tanin来说,可能会有明显的更新答案 - 如果您使用内联模板:
<script type="text/ng-template" id="partial">{{variable}}</script>
<div ng-include-template="'partial'" ng-include-variables="{variable: variable}"></div>
然后,在指令ngIncludeTemplate中,替换
templateUrl: function(elem, attrs) { return attrs.ngIncludeTemplate; },
同
template: function(elem, attrs) { return document.getElementById(attrs.ngIncludeTemplate.split("'")[1]).innerHTML },
以上是关于角度传递范围到ng-include的主要内容,如果未能解决你的问题,请参考以下文章