如何在AngularJS的ngInclude指令中指定模型?

44

我希望在三个地方使用同一个HTML模板,只是每次使用不同的模型。 我知道我可以从模板中访问变量,但它们的名称将不同。

有办法将模型传递给ngInclude吗?

这就是我想要实现的,当然现在属性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方面采取了错误的方法,还有其他我应该尝试的方法吗?


似乎你需要一个指令? - maxisam
一个解决方案是创建一个新的指令,就像我在这个答案中所说的:http://stackoverflow.com/a/36916276/2516399 - smartmouse
6个回答

61

有一个相当简单的解决方案,尽管我必须承认,这不是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/


1
这真的非常聪明,不需要修改Angular或新指令。 - John Hardy
这对我来说非常有效,即使是复杂的数据结构也能处理得很好。 - Trevor de Koekkoek
1
这是目前为止最好的黑科技,直到Angular添加了对传递参数到部分视图的支持。 - Bernard
真正的杰作,也不算太过于投机取巧。 - Saeb Amini
谢谢您!如果我想到了这个方法,我可能会首先尝试使用'ngInit',但是它会自动创建一个“传递”的作用域,而'ngInit'不会这样做。 - MarkMYoung

21

注意:这不是我的原始答案,但这是我在使用Angular一段时间后会做的事情。

我会创建一个指令,将HTML模板作为标记传递给指令,如此Fiddle中所示,将动态数据传递给指令。

以下是此示例的步骤/说明:

  1. 定义具有templateUrl中的标记和用于将数据传递到指令中的属性(在此示例中命名为type)的指令。
  2. 在模板中使用指令数据(在此示例中命名为type)。
  3. 在标记中使用指令时,请确保将控制器范围内的数据传递给指令(例如<address-form type="billing"></address-form>(其中billing是访问控制器范围上的对象)。
  4. 请注意,在定义指令时,名称为驼峰式,但在标记中使用时,名称为小写破折号分隔(即在JS中命名为addressForm,但在HTML中为address-form)。有关此更多信息,请参见Angular文档此处

以下是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>

原始答案(与使用指令完全不同)。

注意:我的原始答案下面的fiddle似乎由于错误而无法工作(但在这里保留,以防它仍然有用)

在Google Group上讨论了这个问题,您可以在此处查看

看起来这个功能不是开箱即用的,但您可以像这篇文章中描述的那样使用Brice的补丁。

这是他的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>

1
谢谢。我成功地通过ng-init实现了它,而不需要新的指令。在这个ng-init中,我创建了objectDetails变量并将其初始化为我想要的内容。 - Tomas Grosup
1
@Imray,我已更改答案以使用指令,这应该可以解决您在仅传递单词而不是从控制器中获取值时遇到的问题。感谢您让我知道现有答案不再完全起作用。 - Gloopy
@Gloopy,我需要在账单数据之外添加一些其他数据。比如说,一些$scope.name="Ankur",但我不能使用type="name",因为它会重新生成视图。在这方面应该怎么做? - Ankur Aggarwal
@AnkurAggarwal 这个 jsfiddle 对你有帮助吗?你可以向被绑定的对象添加任意数量的属性。 - Gloopy
@Gloopy,由于某些限制,我不想将它放在同一个对象中。但是我想在视图中使用特定的作用域属性。 - Ankur Aggarwal
显示剩余4条评论

14

有一个拉请求正在修复这个问题,但看起来它已经死了: 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


1
非常好,谢谢。对我来说,如果我摆脱_ng-init_,只是使用**<div new-scope="myVar = 'one instance'" ng-include="'template.html'"></div>**,看起来更漂亮。(我只是从_ng-init_复制了两行代码到您的指令中,以使其正常工作) - Ande

6
<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 之外,并且你明确地将每个 ng-include 设置为文档、语言或 projectSummary.ProjectResults。 - Gloopy
实际上,我把它放在HTML模板中,因为我很懒。但在每个ng-Include div之前编写它会更加清晰。 - Tomas Grosup
这个会在正确的范围内初始化值吗? 即它是否在包含的范围内设置值? - uriDium
这行代码实际上在内部 HTML 模板中,所以作用域是正确的。 - Tomas Grosup
这正是我一直在寻找的,不知道为什么我之前不知道这个,哈哈。虽然这是目前为止这个问题上最好的答案。 - Playdome.io

1
我明白了!ng-include不太可重用,因为它可以访问全局作用域。这有点奇怪。
应该有一种设置本地变量的方式。使用新指令而不是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中读取对象,并将这些成员添加到它自己的本地作用域中。
它很清晰和通用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接