41

次のように、アプリの複数の場所で and を使用して作成したコントローラーがありng-includeますng-repeat

<div
  ng-repeat="item in items"
  ng-include="'item.html'"
  ng-controller="ItemController"
></div>

コントローラー/テンプレートでは、値が存在することを期待して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>

しかし、それは機能していないようです。このような特異なインスタンスでスコープの変数を渡す方法を知っている人はいますか?

編集: この上のコントローラは、次のような値leftItemと値をロードしています:rightItem

.controller('MainController', function($scope, ItemModel) {
    ItemModel.loadItems()
        .then(function(items) {
            $scope.$apply(function() {
                $scope.leftItem = items.left;
                $scope.rightItem = items.right;
            });
        });
});
4

8 に答える 8

37

パーティーに遅れましたが、ダムディレクティブを実装せずにこれを達成するための少し角度のある「ハック」があります。

コントローラーのスコープ (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>

次に、テンプレート item.html をさまざまなアイテムで数回アイテム変数にバインドできます。

ここにあなたが望むものを達成するためのプランカーがあります

問題は、onload 命令ごとに消去されるアイテム変数への参照を 1 つだけ保持するコントローラー スコープでアイテムが変化し続けることでした。

現在のスコープを拡張するディレクティブを導入すると、すべての ng-include に対して分離されたスコープを持つことができます。結果として、アイテム参照は保持され、すべての拡張スコープで一意になります。

于 2015-09-11T22:13:08.660 に答える
33

これを行うために提供するonload属性を使用できます。ngInclude

<div ng-include="'item.html'"
     ng-controller="ItemController"
     onload="item = rightItem">
</div>

ドキュメントへのリンク

編集

親スコープで次のようなことを試してください。

$scope.dataHolder = {};

次に、非同期データを受信したら、次の場所にデータを保存しますdataHolder

$scope.dataHolder.leftItem = items.leftItem;
$scope.dataHolder.rightItem = items.rightItem;

ng-includeテンプレートをロードすると、親のプロパティを継承する子スコープが作成されます。したがって$scope.dataHolder、この子スコープで定義されます (最初は空のオブジェクトとして)。ただし、非同期データを受信すると、空のオブジェクトへの参照に新しく受信したデータが含まれる必要があります。

于 2014-09-05T04:47:29.590 に答える
13

LOVE @タニンの答え。非常に多くの問題を一度に非常にエレガントな方法で解決します。私のようにCoffeescriptを知らない人のために、ここにjavascriptがあります...

注: 私が理解するにはあまりにも新しいため、このコードでは、テンプレート名を 2 回引用するという ng-include の要件ではなく、テンプレート名を 1 回引用する必要があります。<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];  
      });  
    }  
  }  
})
于 2016-01-11T10:11:50.313 に答える
11

onload の使用は、グローバル スコープを散らかすため、クリーンなソリューションではありません。もっと複雑なものがあると、失敗し始めます。

ng-include は、グローバル スコープにアクセスできるため、それほど再利用可能ではありません。少し変です。

上記は正しくありません。onload を使用した ng-if はグローバル スコープを散らかしません

また、すべての状況に対して特定のディレクティブを書きたいわけではありません。

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>

ディレクティブは次のとおりです。

.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 からオブジェクトを読み取り、それらのメンバーを独自のローカル スコープに追加します。

これがあなたの望むものであることを願っています。それはきれいで一般的です。

于 2015-10-25T18:12:37.957 に答える
4

これには ng-init の方が適していると思います。

<div ng-include='myFile.html' ng-init="myObject = myCtrl.myObject; myOtherObject=myCtrl.myOtherObject"/>
于 2015-11-13T16:19:26.593 に答える
4

上記は、 などの第 2 レベルの属性では機能しません<div ng-include-template=... ng-include-variables="{ id: var.id }">。に注意してvar.idください。

更新されたディレクティブ (醜いが機能します):

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

      scope.$watch(
        function() {
          var val = scope.ngIncludeVariables();
          if (angular.equals(val, cache)) {
            return cache;
          }
          cache = val;
          return val;
        },
        function(newValue, oldValue) {
          if (!angular.equals(newValue, oldValue)) {
            Object.keys(newValue).forEach(function(key) {
              scope[key] = newValue[key];
            });
          }
        }
      );

    }
  };
});
于 2016-04-24T22:31:59.657 に答える
1

マイクとタニンの回答の明らかな更新-インラインテンプレートを次のように使用している場合:

<script type="text/ng-template" id="partial">{{variable}}</script>

<div ng-include-template="'partial'" ng-include-variables="{variable: variable}"></div>

次に、ディレクティブ ngIncludeTemplate で、置き換えます

templateUrl: function(elem, attrs) { return attrs.ngIncludeTemplate; },  

template: function(elem, attrs) { return document.getElementById(attrs.ngIncludeTemplate.split("'")[1]).innerHTML },
于 2016-04-07T10:40:50.883 に答える