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

时间:2012-11-16 19:16:48

标签: html templates angularjs

我想在3个地方使用相同的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采取了不好的方法,我还应该尝试一些其他方法吗?

6 个答案:

答案 0 :(得分: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 :(得分:20)

注意:这不是我原来的答案,但这是我在使用角度稍微做一下后的方法。

我会创建一个带有html模板的指令作为标记,将动态数据传递给指令,如this fiddle中所示。

此示例的步骤/说明:

  1. templateUrl和用于将数据传递到指令的属性(在此示例中名为type)中定义带有标记的指令。
  2. 使用模板中的指令数据(在此示例中名为type)。
  3. 在标记中使用该指令时,请确保将数据从控制器作用域传递到指令(<address-form type="billing"></address-form>(其中计费正在访问控制器作用域上的对象)。
  4. 请注意,在定义指令时,名称是驼峰式的,但在标记中使用时,它是小写破折号分隔符(即在js中命名为addressForm,而在html中命名为address-form。有关此内容的更多信息,请参阅angular docs here
  5. 这是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>
    

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

    注意:由于出现错误,以下原始答案中的小提示似乎不再起作用(但如果它仍然有用,请将其保留在此处)

    您可以在Google网上论坛对此进行讨论see it here

    看起来这个功能不支持开箱即用,但你可以按照this post中的说明使用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>
    

答案 2 :(得分: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

答案 3 :(得分: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&#39; ng-init中的代码结合在一起。

为了完整性,这是Angular 1.2 26 ng-init source,您可以看到新范围指令中唯一的变化是添加了scope: true

{
  priority: 450,
  compile: function() {
    return {
      pre: function(scope, element, attrs) {
        scope.$eval(attrs.ngInit);
      }
    };
  }
}

答案 4 :(得分:5)

Quick'n'dirty解决方案:

<div ng-init="details=document||language||projectSummary.ProjectResults">

答案 5 :(得分:1)

我听到你了! 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读取对象,并将这些成员添加到其自己的本地范围。

它干净而且通用。