分離スコープを持つディレクティブのテンプレートで$ rootScopeにアクセスできないのはなぜですか?


81

分離スコープでは、ディレクティブのテンプレートはコントローラー( 'Ctrl')$ rootScope変数にアクセスできないようですが、ディレクティブのコントローラーには表示されます。コントローラ( 'Ctrl')の$ scope変数が分離スコープに表示されない理由を理解しました。

HTML:

<div ng-app="app">
    <div ng-controller="Ctrl">
        <my-template></my-template>
    </div>

    <script type="text/ng-template" id="my-template.html">
        <label ng-click="test(blah)">Click</label>
    </script>
</div>

JavaScript:

angular.module('app', [])
    .controller('Ctrl', function Ctrl1($scope,  $rootScope) {
        $rootScope.blah = 'Hello';
        $scope.yah = 'World'
    })
    .directive('myTemplate', function() {
        return {
            restrict: 'E',
            templateUrl: 'my-template.html',
            scope: {},
            controller: ["$scope", "$rootScope", function($scope, $rootScope) {
                console.log($rootScope.blah);
                console.log($scope.yah);,

                $scope.test = function(arg) {
                    console.log(arg);
                }
            }]
        };
    });

JSFiddle

変数は、分離スコープなしでアクセスされます-分離スコープの行にコメントを付けるとわかります。

        // scope: {},

$ rootScopeをディレクティブに挿入してみましたか... directive('myTemplate', function($rootScope) { ... })か?
マーククライン2014年

@MarcKline試してみただけで、運が悪かった。
camden_kid 2014年


1
サービスを利用するだけでは不十分な理由はありますか?
マーククライン2014年

1
@ Kalyan-個人的には、$ rootScopeはイベントにのみ使用し、Factoryはデータをディレクティブに渡すために使用する必要があると思います。1つの理由は、$ rootScopeを使用することは、理想的ではないグローバル変数を使用することに似ていることです。また、ファクトリは、後日拡張できる明確に定義されたラッパーにすることができます。
camden_kid 2014

回答:


164

あなたはを使用してこの方法を試すことができます $root.blah

作業コード

html

 <label ng-click="test($root.blah)">Click</label>

javascript

  angular.module('app', [])
    .controller('Ctrl', function Ctrl1($scope,  $rootScope) {
        $rootScope.blah = 'Hello';
        $scope.yah = 'World'
    })
    .directive('myTemplate', function() {
        return {
            restrict: 'E',
            templateUrl: 'my-template.html',
            scope: {},
            controller: ["$scope", "$rootScope", function($scope, $rootScope) {
                console.log($rootScope.blah);
                console.log($scope.yah);

                $scope.test = function(arg) {
                    console.log(arg);
                }
            }]
        };
    });

6
達成したいことを「解決」するので、これを答えとしてマークします(「$ root」またはこのように使用できることを知りませんでした)。ただし、一般的にはMarkKlineの回答が最善の解決策であることをお勧めします。
camden_kid 2014年

5
すごい!$ rootScopeがビューの$ rootに変わることを知っておくと非常に便利です。どうもありがとう!
クリスR

rootScopeで定義された関数にアクセスする必要があったのでこれは完璧です
Alfredo A.

良いもの。ここでも機能しています。$ rootScopeではなく$ rootを使用する理由を説明してください。$ rootScopeも挿入しましたが、関数呼び出し中には未定義です。
Unknown_Coder 2018

32

一般に、$rootScopeコントローラーとディレクティブ間で共有する必要のある値を格納するためにを使用することは避けてください。JSでグローバルを使用するようなものです。代わりにサービスを使用してください:

定数(または値...使用法は類似しています):

.constant('blah', 'blah')

https://docs.angularjs.org/api/ng/type/angular.Module

工場(またはサービスまたはプロバイダー):

.factory('BlahFactory', function() {
    var blah = {
        value: 'blah'
    };

    blah.setValue = function(val) {
      this.value = val;
    };

    blah.getValue = function() {
        return this.value;
    };

    return blah;
})

これがフィドルのフォークで、どちらを使用するかを示しています。


3
+1これと私が達成しようとしていることの正しい方向に私を向けてくれてありがとう。私のコメントに述べられている理由から、NidhishKrishnanは「答え」として受け入れられるべきだと思います。
camden_kid 2014年

1
定数は使用されることがまれであるため、定数のユースケースでは+1。また、$ rootScopeを使用しないことに関する注意はプロのヒントでした。
Farzad YZ 2015

23

1)$scopeコントローラーの分離スコープのためにCtrlとディレクティブコントローラーは同じスコープを参照していません-Ctrlscope2にscope1があるとしましょうディレクティブでは。

2)スコープが分離されているため、scope2 典型的に$rootScope;から継承しません。したがって、定義する$rootScope.blahと、scope2に表示される可能性はありません。

3)ディレクティブテンプレートでアクセスできるのはscope2です

要約すると、これが継承スキーマです

    _______|______
    |            |
    V            V
$rootScope     scope2
    |
    V
  scope1


$rootScope.blah
> "Hello"
scope1.blah
> "Hello"
scope2.blah
> undefined

1
非常に役立ちますが、何らかの方法でrootScope値を使用する必要がある場合は、nidhishkrishnanの回避策が機能します。いいハックです。
マーククライン2014年

1
さて、あなたが言ったことは、なぜ私がhtmlで$ rootScope変数を使用できないのか($ rootなし)に答えるためのロジックですが、Batarangプラグインを使用して$ scopesを表示すると、$がはっきりとわかります。 rootScopeは、他のすべての親$ scopeです(ディレクティブ内の分離されたスコープを含む)。また、角度の公式ドキュメントからの定義は言った:「すべてのアプリケーションは、単一のルートスコープを持っている他のすべてのスコープは、ルートスコープの子孫スコープです。」(docs.angularjs.org/api/ng/service/$rootScope
IsraGab

1

私はこれが古い質問であることを知っています。しかし、分離されたスコープが$ rootscopeのプロパティにアクセスできない理由についての私の質問には満足できませんでした。

だから私は角度のあるlibを掘り下げて見つけました-

$new: function(isolate) {
  var ChildScope,
      child;

  if (isolate) {
    child = new Scope();
    child.$root = this.$root;
    child.$$asyncQueue = this.$$asyncQueue;
    child.$$postDigestQueue = this.$$postDigestQueue;
  } else {

    if (!this.$$childScopeClass) {
      this.$$childScopeClass = function() {
        // blah blah...
      };
      this.$$childScopeClass.prototype = this;
    }
    child = new this.$$childScopeClass();
  }

これは、新しいスコープが作成されるたびにangularによって呼び出される関数です。ここでは、分離されたスコープが典型的にルートスコープを継承していないことは明らかです。むしろ、ルートスコープのみが新しいスコープのプロパティ '$ root'として追加されます。したがって、rootscopeのプロパティには、新しい分離スコープの$ rootプロパティからのみアクセスできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.