如何在 AngularJS 中为 ngInclude 指令指定模型?
Posted
技术标签:
【中文标题】如何在 AngularJS 中为 ngInclude 指令指定模型?【英文标题】:How to specify model to a ngInclude directive in AngularJS? 【发布时间】:2012-11-05 13:18:54 【问题描述】:我想在 3 个地方使用相同的 html 模板,只是每次都使用不同的模型。 我知道我可以从模板中访问变量,但名称会有所不同。
有没有办法将模型传递给 ngInclude?p>
这是我想要实现的,当然属性add-variable现在不行了。然后在我包含的模板中,我将访问 detailsObject 及其属性。
<pane title="projectSummary.ProjectResults.DisplayName">
<h2>projectSummary.ProjectResults.DisplayName</h2>
<ng-include src="'Partials/SummaryDetails.html'" init-variable="'detailsObject': projectSummary.ProjectResults"></ng-include>
</pane>
<pane title="Documents" header="true"></pane>
<pane ng-repeat="document in projectSummary.DocumentResults" title="document.DisplayName">
<h2>document.DisplayName</h2>
<ng-include src="'Partials/SummaryDetails.html'" add-variable="'detailsObject': document"></ng-include>
</pane>
<pane ng-repeat="header in [1]" title="Languages" header="true"></pane>
<pane ng-repeat="language in projectSummary.ResultsByLanguagePairs" title="language.DisplayName">
<h2>document.DisplayName</h2>
<ng-include src="'Partials/SummaryDetails.html'" add-variable="'detailsObject': language"></ng-include>
</pane>
如果我在使用 ng-include 时采取了不好的方法,我还应该尝试其他方法吗?
【问题讨论】:
你好像需要一个指令? 一个解决方案是创建一个新指令,正如我在这个答案中所说:***.com/a/36916276/2516399 【参考方案1】:有一个相当简单的解决方案,虽然我必须承认,这不是 Misko 推荐的。但是,如果创建指令对您来说太过分了,并且获得 Brice 的补丁也不可行,那么以下内容将对您有所帮助。
<div ng-repeat="name in ['A']" ng-include="'partial.html'"></div>
<div ng-repeat="name in ['B']" ng-include="'partial.html'"></div>
<script type="text/ng-template" id="partial.html">
<div> name </div>
</script>
它为什么起作用是很明显的。在此处查看示例:http://jsfiddle.net/Cndc6/4/
【讨论】:
这真是太棒了,不需要修改角度或新指令。 这对我来说非常适合复杂的数据结构。 这是迄今为止最好的 hack,直到 Angular 添加支持将参数传递给部分。 真的很出色,而且也不是什么黑客行为。 谢谢你!如果我的想法走这条路,我可能会首先尝试使用'ngInit',但这会自动生成一个'ngInit'没有的“嵌入”范围。【参考方案2】:注意:这不是我最初的答案,但这是我在使用 angular 一段时间后的做法。
我将使用 html 模板创建一个指令作为将动态数据传递给指令的标记,如 this fiddle 所示。
此示例的步骤/注释:
-
使用
templateUrl
中的标记和用于将数据传递到指令中的属性定义一个指令(在本例中命名为type
)。
使用模板中的指令数据(在本例中命名为type
)。
在标记中使用指令时,请确保将数据从控制器范围传递到指令(<address-form type="billing"></address-form>
(其中计费正在访问控制器范围内的对象)。
请注意,在定义指令时,名称是驼峰式大小写,但在标记中使用时,它是小写破折号分隔(即它在 js 中命名为 addressForm
,但在 html 中命名为 address-form
)。有关这方面的更多信息,请参阅 angular 文档 here。
这里是js:
var myApp = angular.module('myApp',[]);
angular.module('myApp').directive('addressForm', function()
return
restrict: 'E',
templateUrl: 'partials/addressform.html', // markup for template
scope:
type: '=' // allows data to be passed into directive from controller scope
;
);
angular.module('myApp').controller('MyCtrl', function($scope)
// sample objects in the controller scope that gets passed to the directive
$scope.billing = type: 'billing type', value: 'abc' ;
$scope.delivery = type: 'delivery type', value: 'def' ;
);
带标记:
<div ng-controller="MyCtrl">
<address-form type="billing"></address-form>
<address-form type="delivery"></address-form>
</div>
ORIGINAL ANSWER(这与使用指令 BTW 完全不同)。
注意:由于错误,我在下面的原始答案中的小提琴似乎不再起作用(但请保留它以防它仍然有用)
Google Group 上有关于此的讨论,您可以see it here。
看起来此功能不支持开箱即用,但您可以使用 Brice 的补丁,如 this post 中所述。
这是他jsfiddle的示例代码:
<script id="partials/addressform.html" type="text/ng-template">
partial of type type<br>
</script>
<div ng-controller="MyCtrl">
<ng-include src="'partials/addressform.html'" onInclude="type='billing'"></ng-include>
<ng-include src="'partials/addressform.html'" onLoad="type='delivery'"></ng-include>
</div>
【讨论】:
谢谢。我设法在没有新指令的情况下使用 ng-init 实现了它。在这个 ng-init 中,我创建了 objectDetails 变量并将其初始化为我想要的。 现在您可以使用自己的 directive 并在其中使用 templateUrl 属性。 使用type='delivery'
只是给了我delivery
这个词,而不是来自控制器的delivery
值。 -1
@Imray 我已将答案更改为使用指令,而不是通过传递一个单词而不是来自控制器的值来解决您遇到的问题。感谢您让我知道现有答案不再有效。
@Gloopy 我还需要添加一些其他数据以及计费。假设一些 $scope.name="Ankur" 我不能做 type="name" 因为它会再次生成视图。这方面该怎么办?【参考方案3】:
有一个解决这个问题的方法,但它看起来已经死了: https://github.com/angular/angular.js/pull/1227
在不修改 Angular 源代码的情况下,这将以一种可重用的不太老套的方式解决问题:
directive('newScope', function()
return
scope: true,
priority: 450,
;
);
还有一个例子:
<div new-scope ng-init="myVar = 'one instance'" ng-include="'template.html'"></div>
<div new-scope ng-init="myVar = 'another instance'" ng-include="'template.html'"></div>
这是它的一个 Plunker: http://plnkr.co/edit/El8bIm8ta97MNRglfl3n
【讨论】:
效果很好,谢谢。对我来说,如果我摆脱 ng-init 并只拥有 。 (我刚刚将 ng-init 中的两行代码复制到您的指令中以使其正常工作)【参考方案4】:<div new-scope="myVar = 'one instance'" ng-include="'template.html'"></div>
directive('newScope', function ()
return
scope: true,
priority: 450,
compile: function ()
return
pre: function (scope, element, attrs)
scope.$eval(attrs.newScope);
;
;
);
这是一个指令,它结合了来自 John Culviner's answer 的 new-scope
和来自 Angular 的 ng-init
的代码。
为了完整起见,这是Angular 1.2 26 ng-init source,您可以看到new-scope指令中唯一的变化是添加了scope: true
priority: 450,
compile: function()
return
pre: function(scope, element, attrs)
scope.$eval(attrs.ngInit);
;
【讨论】:
【参考方案5】:快速解决方案:
<div ng-init="details=document||language||projectSummary.ProjectResults">
【讨论】:
不错的解决方法,因此您的 div 位于每个 ng-include 之外,并且您将每个 div 明确设置为文档、语言或 projectSummary.ProjectResults? 其实我把这个放在html模板里面,因为我比较懒。但是在每个 ng-Include div 之前编写它会更干净。 这会在正确的范围内初始化值吗? IE。它是否在包含范围内设置值? 这一行其实是在内部html模板里面,所以是的,范围是正确的。 这就是我一直在寻找的东西,我不知道为什么我不知道这个已经大声笑了。虽然这是迄今为止这个问题的最佳答案。【参考方案6】:我听到了! ng-include 不是那么可重用,因为它可以访问全局范围。有点奇怪。
应该有一种设置局部变量的方法。 Using a new directive instead of ng-include 是一种更清洁的解决方案。
理想的用法如下:
<div ng-include-template="'Partials/SummaryDetails.html'" ng-include-variables=" 'detailsObject': language "></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 读取对象并将这些成员添加到自己的本地范围内。
它干净而通用。
【讨论】:
以上是关于如何在 AngularJS 中为 ngInclude 指令指定模型?的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS ng-include 不包含视图,除非传入 $scope
AngularJS – 如何在 Jasmine 中为输入事件指令编写单元测试
如何在 Rails 4 中为 AngularJS 更正设置根路由?