不同的ng-include在同一页面上:如何向每个变量发送不同的变量?

时间:2012-12-11 00:57:52

标签: angularjs

我的AngularJS应用程序中有一个页面,我想在其中包含相同的html部分,但具有不同的变量。如果我在我的主html中执行此操作:

<div id="div1" ng-include src="partials/toBeIncluded.html onload="var='A'">
<div id="div2" ng-include src="partials/toBeIncluded.html onload="var='B'">

toBeIncluded.html看起来像

<div>{{var}}</div>

两个div都看起来像

<div id="div1"><div>B</div></div>
<div id="div2"><div>B</div></div>

我想这与为ng-includes调用相同的onload这一事实有关。那么如何将不同的变量发送到每个不同的包含?

15 个答案:

答案 0 :(得分:39)

每次加载新部分时,传递给onload的表达式都会计算。在这种情况下,您要将var的值更改两次,以便在加载两个部分时,当前值将为B

您希望将不同的数据传递给每个部分/模板(底层的html文件是相同的)。为了实现这一点,正如Tiago所提到的,你可以用不同的控制器来做到这一点。例如,请考虑以下

<body ng-controller='MainCtrl'>    
  <div ng-include src='"toBeIncluded.html"' ng-controller='ctrlA' onload="hi()"></div>
  <div ng-include src='"toBeIncluded.html"' ng-controller='ctrlB' onload="hi()"></div>
</body>

在这里,我们有两个部分,每个部分都有自己的范围,由自己的控制器(ctrlActrlB)管理,两个子范围都是MainCtrl。函数hi()属于MainCtrl的范围,将运行两次

如果我们有以下控制器

app.controller('MainCtrl', function($scope) {
  $scope.msg = "Hello from main controller";
  $scope.hi= function(){console.log('hi');};
});

app.controller('ctrlA', function($scope) {
  $scope.v = "Hello from controller A";
});

app.controller('ctrlB', function($scope) {
  $scope.v = "Hello from controller B";
});

toBeIncluded.html的内容是

<p>value of msg = {{msg}}</p>
<p>value of v = {{v}} </p>

生成的html将是以下几行

<p>value of msg = Hello from main controller</p>
<p>value of v = Hello from main controller A </p>

<p>value of msg = Hello from main controller</p>
<p>value of v = Hello from controller B </p>

此处示例:http://plnkr.co/edit/xeloFM?p=preview

答案 1 :(得分:26)

就像马克所说的那样,但是为了简化它并使其更加“在飞行中”是使用以下内容:

<div ng-repeat="name in ['John']" ng-include="'name-template.html'"></div>
<div ng-repeat="name in ['Jack']" ng-include="'name-template.html'"></div>

<script type="text/ng-template" id="name-template.html">
   <div>The name is {{ name }}</div>
<script>

此处示例:http://jsfiddle.net/Cndc6/4/

答案 2 :(得分:20)

在你对@jm-答案的评论中,你提到你想加载部分内部ng-repeat。为此,请在$ scope上创建一个数组,并在该数组上设置唯一值:

$scope.partialStuff = [ 'p1', 'p2', 'p3' ];

你偏爱中的某个地方:

{{partialVar}}

HTML:

<div ng-repeat="partialVar in partialStuff">
   <div ng-include src="'partials/toBeIncluded.html'"></div>
</div>

Fiddle

答案 3 :(得分:10)

我可能错了,但使用指令会不会更好?

.directive('foobar', [function factory() {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: '/toBeIncluded.html',
        scope: {
            "var": "="
        }
    };
}]);

和你的HTML

<div ng-repeat="var in data">
    <foobar var="var"></foobar>
</div>

现在应该用模板替换foobar元素。每个人都拥有自己的范围。

答案 4 :(得分:1)

具体来说,ng-init和onload表达式在范围内进行评估,而不是由nginclude创建的子范围。因此,您要在父作用域上为var赋值两次,这两个值都是在编译和评估这些ng-includes内的内容之前发生的。创建每个子作用域时,它继承自父作用域,其中var ='B'。

答案 5 :(得分:1)

考虑你的部分内部有变量foo,

然后你会像这样传递foo:

<ng-include src="'partials/foo-part.html'" onLoad="foo='bar'"></ng-include>

为了获得更多浏览器兼容性,您可以像这样传递:

<div ng-include src="'partials/foo-part.html'" onLoad="foo='bar'"></div>

您也可以使用onInclude="foo='bar'"代替onLoad

plnkr.co/edit/GHRNyAMBKLvgtf3NFSRu?p=info

答案 6 :(得分:0)

所有ng-includes都没有调用相同的“onLoad”。最有可能的是,var设置为A,然后设置为B.事实上,它在两个包含中共享,因为它们位于相同的范围内。 'var'作为angularJS中的模型,取决于范围。

为了使您的部分具有单独的值,它们必须各自具有自己的范围。最简单的方法是设置一个控制器或指令,并将其分配给ng-include所在的Dom元素,并在该范围内设置你的值。

答案 7 :(得分:0)

我遇到了同样的问题,我找到了实现我想要的方法 当然它看起来不是很漂亮但仍然。

我使用了ng-repeat,这将创建一个新的范围,包括两个相同的模板,使用不同的值,如此(虚拟示例):

<script type="text/ng-template" id="mod-edito.html">
<div class="mod-edito__media">
    <img ng-src="{{ edito.cover.src }}" />
</div>
</script>

<div>
    <ng-include ng-repeat="edito in [edito_object]" src="'mod-edito.html'"></ng-include>
    ...
    <ng-include ng-repeat="edito in [edito_other]" src="'mod-edito.html'"></ng-include>
</div>

这可以接受吗?我想是的。

答案 8 :(得分:0)

我正在寻找替代方案,我想要一个js对象将一些参数发送到包含的部分中。 {@ 3}}由@ denis-pshenov制作的This is the evolved version。您可以使用控制器来填充数据,也可以使用ng-init。

基本上,像这样,

&#13;
&#13;
var myApp = angular.module('myApp',[]);

myApp.controller('Controller', function($scope) {
    $scope.ourData = [ { name : 'John', address : 'Paradise' } ];
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="Controller">
    <div ng-repeat="data in ourData" ng-include="'partial.html'"></div>
    
    <div ng-init="ourData2 = [ { name : 'Jack', address : 'Paradise' } ]" />
    <div ng-repeat="data in ourData2" ng-include="'partial.html'"></div>
    
</div>

<script type="text/ng-template" id="partial.html">
   <div>The name is {{ data.name }} and the address is {{ data.address }} </div>
</script>
&#13;
&#13;
&#13;

答案 9 :(得分:0)

有一种方法可以创建通用的可重用指令。

以下是我的一位同事提出的建议(灵感来自Knockout.js)。

指令:

(function () {
    'use strict';

    angular
        .module('directives')
        .directive('ngWith', ngWith);

    function ngWith() {
        return {
            restrict: 'A',
            replace: true,
            scope: {
                model: '=',
                template: '@'
            },
            template: '<div data-ng-include="template"></div>',
        };
    }
})();

用法:

<div data-ng-with="" data-model="parentObj.childObj.whatEver" data-template='my-template.html'></div>

答案 10 :(得分:0)

如果您将部分纳入ng-repeat,您仍然可以访问父作用域的$ index。只需在部分内包含{{$ index}}。

答案 11 :(得分:0)

使用onload不是一个干净的解决方案,因为它会占用全局范围。如果你有更复杂的东西,它将开始失败。

Using a new directive instead of ng-include是一个更清洁的解决方案。

理想用法如下:

<div ng-include-template="partials/toBeIncluded.html" ng-include-variables="{ var: 'A' }"></div>
<div ng-include-template="partials/toBeIncluded.html" ng-include-variables="{ var: 'B' }"></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-include不是可重用的,因为它可以访问全局范围。这有点奇怪。

我希望这是你想要的;它干净而且通用。

答案 12 :(得分:0)

您可以参考单个值(如$scope.a = 'test')和$scope.a = {a.test};等对象的特征,并使用不同的范围来定义可见区域。

来自ng-if文档。

  

请注意,使用ngIf删除元素时,其范围将被销毁,并在元素恢复时创建新范围。

Simpe解决方案是包含ng-if并将静态标准定义为ng-init指令。

<div ng-if="<any-true-expression>" ng-init="val='First'" ng-include="'html/common.html'"</div>

<div ng-if="<any-true-expression>" ng-init="val='Second'" ng-include="'html/common.html'"</div>

在这种情况下,它将显示不同的值,如

{{val}} shows >>
First
Second

此内容是静态的,因为val是对值的简单引用。

如果您希望拥有依赖于某些常见范围值的动态可更改页面,则需要销毁并重新创建使用指令ng-if时创建的范围。像这样:

<div id="wrapper" ng-if="orders_client">
       <div id="client-orders" ng-init="orders = orders_client" ng-include="'html/pages/parts/orders-view.html'"></div>
</div>

$scope.orders_client = null;
   /*recreate content table*/
     $timeout(function () {
        $rootScope.general.showPreloader = false;
        $scope.orders_client = $scope.baseData.clients[newClient];
     }, 500);

在这种情况下,将销毁具有先前数据的范围,并将创建具有新数据的新范围。需要时间重建新范围 500ms 。如果存在更好的捕获,请写下。

答案 13 :(得分:0)

每次通过ng-if=true加载局部时,都可以使用ng-include强制使用新作用域。

您的代码如下

<div id="div1" ng-include src="partials/toBeIncluded.html onload="var='A'" ng-if="true">
<div id="div2" ng-include src="partials/toBeIncluded.html onload="var='B'" ng-if="true">

可以在此plunker

找到一个示例

另一个答案引用了相同的想法here

答案 14 :(得分:-3)

只需将每个ng-include置于其自己的<div>下,如下所示:

<div>
  <div id="div1" ng-include src="partials/toBeIncluded.html onload="var='A'"/>
</div>
<div>
  <div id="div2" ng-include src="partials/toBeIncluded.html onload="var='B'"/>
</div>

每个包含的HTML都会在自己的范围内拥有自己的var