web-dev-qa-db-ja.com

AngularJS:ng-includeおよびng-controller

私は角度で構築しているアプリを持っています、私は構築するために約8-10のビューを持っています。すべてのビューには、フッター上のコンテンツの一部を条件付きで表示/非表示にする必要があるビューと一連のビジネスルールに基づいて、共有フッターがあります。

そう。ビューごとにコントローラーがあり、フッター用にコントローラーがあります。 ng-includeを使用して一般的なフッターレイアウトをインクルードします。ここでインクルードするhtmlは、ng-controllerのフッターコントローラーを参照します。

Index.html

<body ng-controller="MainCtrl as vm">
    <p>Message from Main Controller '{{vm.mainMessage}}'</p>
    <div ng-include="'commonFooter.html'"></div>
</body>

commonFooter.html

<div ng-controller="FooterCtrl as vm">
    <p>Message from Footer Controller '{{vm.message}}'</p>
    <p ng-show="vm.showSomthing">Conditional footer Content</p>
</div>

各View Controllerでフッターの状態と特定のコンテンツが非表示になっているかどうかを判断する必要があります。 (下記のshouldDisplaySomthingInFooter)

app.controller('MainCtrl', function($scope) {
  var vm = this;
  vm.mainMessage= 'HEELO';
  vm.shouldDisplaySomthingInFooter = true;
  window.console.log('Main scope id: ' + $scope.$id);
});

次に、FooterControllerで親コントローラーに戻り、特定の設定を引き出して、ビジネスルールに基づいてコンテンツを有効/無効にすることを意図していました。

app.controller('FooterCtrl', function($scope) {
    var vm = this;
  vm.message = 'vm footer';

  window.console.log('Footer scope id: ' + $scope.$id);
  window.console.log('Footer parent scope id: ' + $scope.$parent.$id);
  window.console.log('Footer grandparent scope id: ' + $scope.$parent.$parent.$id);
  window.console.log('Footer grandparent scope name: ' + $scope.$parent.$parent.mainMessage);
  window.console.log('Footer grandparent scope condition: ' + $scope.$parent.$parent.shouldDisplaySomthingInFooter);

  vm.showSomthing = false; //how to pull from parent scope to bind the ng-show to a value set in the parent from within a ng-include?
});

私はここにこの例を持っています: http://plnkr.co/edit/ucI5Cu4jjPgZNUitY2w0?p=preview

私が見つけているのは、親スコープに到達して、未定義として戻ってくるコンテンツを引き出すために、私はなぜかわからないということです。

Scopeidをチェックすると、スコープが祖父母レベルにネストされていることがわかります。これは、ng-includeがビュースコープの下に追加のスコープレイヤーを追加するためだと考えています。 outout from console in attached example

余分なポイント:$ scopeオブジェクトを使用する必要がなく、var vm = this;望ましい方法。しかし、be食は選択者にはなれません:)

app.controller('MainCtrl', function($scope) {
  var vm = this;

事前にどうもありがとうございました。

26
DShorty

外部コントローラーをvmとしてスコープし、内部コントローラーをfooとしてスコープする場合、それらを簡単に分離し、内部コントローラー内でvmを参照できます。

デモ

[〜#〜] html [〜#〜]

<body ng-controller="MainCtrl as vm">
    <p>Message from Main Controller '{{vm.mainMessage}}'</p>
    <div ng-include="'commonFooter.html'"></div>
</body>

CommonFooter.html

<div ng-controller="FooterCtrl as footer">
    <p>Message from Footer Controller '{{footer.message}}'</p>
    <p ng-show="vm.shouldDisplaySomethingInFooter">Conditional footer Content</p>
</div>

app.js

var app = angular.module('plunker', []);

app.controller('MainCtrl', function() {
    var self = this;
    self.mainMessage = 'Hello world';
    self.shouldDisplaySomethingInFooter = true;
});

app.controller('FooterCtrl', function() {
    var self = this;
    self.message = 'vm footer';
});

注:わかりやすくするため、およびビューとコントローラー間の混乱を減らすために、var vm = thisvar self = thisに名前変更しました。

期待される出力:

output showing the conditionally hidden\shown items

31
Kyle Muir

controller as構文( ドキュメントを参照 )の使用目的を誤解しています。これは、ローカルスコープで特定のコントローラーを公開する方法であり、テンプレートからそのプロパティにアクセスできます。親テンプレートとフッターテンプレートの両方でsomeController as vmを使用する場合、何らかの形でコントローラーまたはそのようなものの間に接続を作成しません。フッターのスコープでvmプロパティを設定しているだけなので、フッターテンプレートで使用すると、フッターのコントローラーにアクセスします(親コントローラーへのアクセスをブロックしました)。

あなたがやろうとしていることのために、基本的にはcontroller as構文はまったく必要ありません。 $scopeにデータを適切に配置し、残りをスコープ階層に任せるだけです。

親コントローラーで:

$scope.features.rock = true;
$scope.features.roll = false;

フッターテンプレート内

<p ng-show="features.rock">...</p>
<p ng-show="features.roll">...</p>

また、他のコントローラーからfeaturesを表示および変更できます(それらのスコープは親コントローラーのスコープの子孫であるため)。

3
hon2a

私はあなたのプランカーをいじりましたが、var vm = this;$scopeに変更したので、余分な点で失敗しています:-)

$scope.$parentの使用は、あなたが示す理由とまったく同じ理由で強くお勧めします。 ng-includeng-showなどのさまざまなディレクティブは、独自のスコープを生成します。

将来誰かがあなたのhtmlを変更し、意図的またはその他の方法でスコープを追加するかどうかは制御できません。

MainCtrlにある関数を使用し、スコープを継承してアクセスすることをお勧めします。

Plunker

$scope.getShouldShow = function() {
    return $scope.shouldDisplaySomthingInFooter;
  };
  $scope.setShouldShow = function(val) {
    $scope.shouldDisplaySomthingInFooter = val;
  };

  $scope.getMainMessage = function () {
    return $scope.mainMessage;
  }

そしてそれらを呼び出す:

<p ng-show="getShouldShow();">Conditional footer Content</p>

そして:

  window.console.log('Footer grandparent scope name: ' + $scope.getMainMessage());
  window.console.log('Footer grandparent scope condition: ' + $scope.getShouldShow());
2
Omri Aharon