角度传递范围到ng-include

kbj*_*bjr 39 javascript angularjs angularjs-ng-repeat angularjs-ng-include angularjs-ng-init

我有一个控制器,我写的,我在多个地方使用我的应用程序ng-includeng-repeat,就像这样:

<div
  ng-repeat="item in items"
  ng-include="'item.html'"
  ng-controller="ItemController"
></div>
Run Code Online (Sandbox Code Playgroud)

在控制器/模板中,我希望item价值存在,而整个事物都围绕着这个想法.但是,现在,我需要以稍微不同的方式使用控制器,没有ng-repeat,但仍然需要能够传入item.我看到ng-init并认为它可以做我需要的,像这样:

<div
  ng-init="item = leftItem"
  ng-include="'item.html'"
  ng-controller="ItemController"
></div>
<div
  ng-init="item = rightItem"
  ng-include="'item.html'"
  ng-controller="ItemController"
></div>
Run Code Online (Sandbox Code Playgroud)

但这似乎并没有奏效.任何人都有任何想法如何在像这样的单一实例中传入变量的范围?

编辑:上面的控制器正在加载leftItemrightItem值,如下所示:

.controller('MainController', function($scope, ItemModel) {
    ItemModel.loadItems()
        .then(function(items) {
            $scope.$apply(function() {
                $scope.leftItem = items.left;
                $scope.rightItem = items.right;
            });
        });
});
Run Code Online (Sandbox Code Playgroud)

Sun*_* D. 33

您可以使用提供的onload属性ngInclude执行此操作:

<div ng-include="'item.html'"
     ng-controller="ItemController"
     onload="item = rightItem">
</div>
Run Code Online (Sandbox Code Playgroud)

链接到文档.

编辑

尝试在父作用域中执行以下操作:

$scope.dataHolder = {};
Run Code Online (Sandbox Code Playgroud)

然后,当收到异步数据时,将数据存储在dataHolder:

$scope.dataHolder.leftItem = items.leftItem;
$scope.dataHolder.rightItem = items.rightItem;
Run Code Online (Sandbox Code Playgroud)

现在,在ng-include加载模板时,它将创建一个继承父项属性的子作用域.因此$scope.dataHolder将在此子范围中定义(最初作为空对象).但是当收到异步数据时,对空对象的引用应该包含新接收的数据.


Pio*_*iou 33

晚到派对,但有一个有点角度'黑客'来实现这一点,而不实施一个哑巴指令.

添加一个内置指令,可以扩展控制器的范围(如ng-if),无论你在哪里使用ng-include,实际上都可以让你为所有包含的范围隔离变量名.

所以:

<div ng-include="'item.html'"
  ng-if="true"
  onload="item = rightItem">
</div>
<div ng-include="'item.html'"
  ng-if="true"
  onload="item = leftItem">
</div>
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用不同的项目将模板item.html多次绑定到项目变量.

这是一个实现你想要的东西

问题是项目在控制器范围内不断变化,只保存对每个onload指令中擦除的项目变量的一个引用.

引入扩展当前范围的指令,使您可以为所有ng-include提供隔离范围.因此,项目引用在所有扩展范围内都保留并且是唯一的.

  • 谢谢,这完美无缺.提示:我发现添加一个在加载(异步)后动态填充的值,因为它在评估include语句时不可用,但是将if语句更改为ng-if ="myVariable" "所以它只会在myVariable填充时加载解决该问题. (6认同)
  • 完美的主意.工作得很好.ng-if是一个很好的技巧 (2认同)

kbj*_*bjr 17

我最终将它重写为一个指令并将范围内的所需值绑定到

scope: {
    item: '='
}
Run Code Online (Sandbox Code Playgroud)

  • 投票,因为ng-init =""和onload =""似乎不起作用,虽然它们应该...但遗憾的是我们每次都需要为这个简单的任务创建一个指令. (2认同)

Mik*_*ike 12

爱@ Tanin的回答.解决了这样一次和一个非常优雅的方式很多问题.对于那些不喜欢Coffeescript的我喜欢的人,这里是javascript ...

注意:由于我太难理解的原因,此代码要求您引用模板名称一次,而不是ng-include要求两次引用模板名称,即.<div ng-include-template="template-name.html" ... >代替<div ng-include-template="'template-name.html'" ... >

.directive('ngIncludeTemplate', function() {  
  return {  
    templateUrl: function(elem, attrs) { return attrs.ngIncludeTemplate; },  
    restrict: 'A',  
    scope: {  
      'ngIncludeVariables': '&'  
    },  
    link: function(scope, elem, attrs) {  
      var vars = scope.ngIncludeVariables();  
      Object.keys(vars).forEach(function(key) {  
        scope[key] = vars[key];  
      });  
    }  
  }  
})
Run Code Online (Sandbox Code Playgroud)


Tan*_*nin 11

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

ng-include不是可重用的,因为它可以访问全局范围.这有点奇怪.

以上情况并非如此.ng-if with onload不会乱丢全局范围

我们也不想为每种情况编写特定的指令.

制定通用指令而不是ng-include是一种更清晰的解决方案.

理想的用法如下:

<div ng-include-template="'item.html'" ng-include-variables="{ item: 'whatever' }"></div>
<div ng-include-template="'item.html'" ng-include-variables="{ item: variableWorksToo }"></div>
Run Code Online (Sandbox Code Playgroud)

该指令是:

.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
    }
)
Run Code Online (Sandbox Code Playgroud)

您可以看到该指令不使用全局范围.相反,它从ng-include-variables读取对象并将这些成员添加到其自己的本地范围.

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