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

Different ng-include's on the same page: how to send different variables to each?

我的AngularJS应用程序中有一个页面,我希望在其中包含相同的HTML部分,但变量不同。如果我在我的主html中这样做:

1
 

toBeIncluded.html看起来像

1
{{var}}

两个div看起来都像

1
2
B
B

我想这是因为同样的onload被要求使用al-the-ng。那么,如何向每个不同的include发送不同的变量呢?


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

您希望将不同的数据传递给每个部分/模板(基础HTML文件相同)。要实现这一点,正如Tiago提到的,您可以使用不同的控制器。例如,考虑以下内容

1
2
3
4
<body ng-controller='MainCtrl'>    
 
 
</body>

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

如果我们有以下控制器

1
2
3
4
5
6
7
8
9
10
11
12
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的内容是

1
2
3
4
5
6
<p>
value of msg = {{msg}}
</p>
<p>
value of v = {{v}}
</p>

生成的HTML将是以下几行中的某个内容

1
2
3
4
5
6
<p>
value of msg = Hello from main controller
</p>
<p>
value of v = Hello from main controller A
</p>

1
2
3
4
5
6
<p>
value of msg = Hello from main controller
</p>
<p>
value of v = Hello from controller B
</p>

例如:http://plnkr.co/edit/xelofm?P=预览


正如马克所说的,但要简化一点,使其更"即时"是使用以下方法:

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

示例:http://jsfiddle.net/cndc6/4/


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

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

在你的部分:

1
{{partialVar}}

HTML:

1
 

小提琴。


我可能是错的,但使用指令不是更好吗?

1
2
3
4
5
6
7
8
9
10
.directive('foobar', [function factory() {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: '/toBeIncluded.html',
        scope: {
           "var":"="
        }
    };
}]);

还有你的HTML

1
    <foobar var="var"></foobar>

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


假设你的部分中有变量foo,

然后你会像这样通过foo:

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

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

1
 

你也可以用onInclude="foo='bar'"代替onload

plnkr.co/edit/ghrnyambklvgtf3nfsru?P=信息


具体来说,ng init和onload表达式是在父作用域中计算的,而不是由nginclude创建的子作用域。因此,您要在父作用域上为var分配两次值,这两次都发生在加载、编译和评估这些ng-include中的内容之前。当创建每个子作用域时,它从父作用域继承,其中var='b'。


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

来自ng if文档。

Note that when an element is removed using ngIf its scope is destroyed and a new scope is created when the element is restored.

简单的解决方案是将ng-if包括在内,并将静态conetent定义为ng-init指令。

1
2
3
" ng-init="val='First'" ng-include="'html/common.html'"

" ng-init="val='Second'" ng-include="'html/common.html'"

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

1
2
3
{{val}} shows >>
First
Second

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

如果您希望具有动态可更改的页面,这取决于一些公共范围值,则需要销毁并重新创建在使用指令ng-if时创建的范围。这样地:

1
 

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

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


使用onload不是一个干净的解决方案,因为它会破坏全局范围。如果你有更复杂的事情,它就会开始失败。

使用新的指令而不是ng include是一个更干净的解决方案。

理想用法如下:

1
 

指令是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.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变量,并将这些成员添加到自己的本地范围中。

ng include没有那么可重用,因为它可以访问全局范围。有点奇怪。

我希望这是你想要的,它是干净的,通用的。


只是一个提示,如果在ng repeat中包含部分内容,您仍然可以访问父作用域的$index。只需在部分中包含$index。


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

这是我的一个同事想出的(灵感来自knockout.js)。

指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(function () {
    'use strict';

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

    function ngWith() {
        return {
            restrict: 'A',
            replace: true,
            scope: {
                model: '=',
                template: '@'
            },
            template: '',
        };
    }
})();

用途:

1
 

我在寻找一个替代方法,我想要一个JS对象向包含的部分发送一些参数。这是@denis pshenov制作的版本的进化版本。您可以使用控制器来填充数据,或者使用ng init。

基本上,像这样,

1
2
3
4
5
var myApp = angular.module('myApp',[]);

myApp.controller('Controller', function($scope) {
    $scope.ourData = [ { name : 'John', address : 'Paradise' } ];
});
1
2
3
4
5
6
7
8
9
10
11
12
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">

   
   
   
   
   


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


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

我使用了ng repeat,它将创建一个新的范围来包含非常相同的模板,两次使用不同的值,如so(虚拟示例):

1
2
3
4
5
6
7
8
9
10
<script type="text/ng-template" id="mod-edito.html">

    <img ng-src="{{ edito.cover.src }}" />




    <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>

可以接受吗?我想是的。


同样的"onload"并不能用于所有ng-include。很可能,var被设置为a,然后设置为b。问题是,它在两个includes之间被共享,因为它们在同一个范围内。‘var’,作为AngularJS中的一个模型,取决于作用域。

为了使分区具有单独的值,它们必须各自具有自己的作用域。最简单的方法是设置控制器或指令,并将其分配给包含ng的dom元素,然后在该范围内设置值。


只需将每个NG包括在其自身的下,如下所示:

1
 

然后,每个包含的HTML都将在其自己的范围内拥有自己的var