web-dev-qa-db-ja.com

Angularjs-ディレクティブリンク関数の$ rootScope

ルートスコープをディレクティブに渡される依存関係と考える方法が明確ではないため、この質問をしています

$ rootScopeからの情報を表示する必要があるディレクティブがあります...

$ rootScopeをディレクティブに渡す必要があると思いましたが、このようなディレクティブを作成すると、うまくいくようです。

.directive("myBar", function () {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

いつこれを行う必要がありますか?

.directive("myBar", function ($rootScope) {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

ディレクティブのリンク関数で必要な場合、rootScopeを使用できますか-または、ディレクティブのコントローラーで行う必要がありますか?

.directive("myBar", function ($rootScope) {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    link: function (scope, element, attrs, rootScope) {
        rootScope.rsUser = { firstName: 'Joe' };
        rootScope.rsUser = { welcome: 'Welcome' };
    },
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

RootScopeデータはrun関数で定義されています

 .run(function ($rootScope) {

  $rootScope.rsLabels = { 
      welcome: 'Welcome'
  };

  $rootScope.rsUser = { 
     firstName: 'Joe'
  };
});

ありがとうございました!

47
GRowing

私の実験の経験から、すべての$ scopeは最終的に$ rootScopeから継承するので、標準のJavaScriptの典型的な継承ルールに従って、サービスとして要求することなくそのデータにアクセスできるようです。ディレクティブのスコーププロパティをfalseまたは{}に設定すると、アクセスできなくなります。

.directive("myBar", function($rootScope) {
    return {
        restrict: "E",
        scope: { /* Isolate scope, no $rootScope access anymore */ },
        transclude: true,
        replace: true,
        template: '<div>' + 
                  '<span ng-transclude></span>' + 
                  '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                  '</div>'
    };
});

例: http://jsbin.com/bequy/1/edit

51
Mike Cheel

この方法でできます:

{{$root.rsLabels.welcome}}
66
karaxuna

ルートスコープを使用してangularアプリケーションのプロパティを設定および取得することはお勧めしません。 $ cacheFactoryを使用してみてください。さまざまなリクエストでいくつかの値をキャッシュすることもできます。 ( $ cacheFactory docs

7
Kurt Du Bois

時々$ scope。$ rootを使用する必要があります:

app.directive('setOrdinal', function() {
  return {
    link: function($scope, $element, $attr) {

      var steps = $scope.$root.steps;

      $scope.$watch(setOrdinal, function(value) {
        if (value)
        {
          // steps code here
        }
      });
    }
  };
});

app.controller('stepController', ['$scope', '$rootScope', 'GetSteps', function ($scope, $rootScope, GetSteps) {
  var s = $scope;
  var r = $rootScope;

  s.initialize = function(id)
  {
    GetSteps.get({id: id}, function(resp){
      r.steps = resp.steps;
    });
  };
}]);
4
omikes

この同じ質問にかなりの時間を費やした後、最初の投稿で無視されたことに注目する価値があると思いました。ここに私の元のコードがあります:

app.directive('countrymap', function() 
{
    return {
        link: function(scope, element, attrs) {
            scope.$watch("countryMap", function (newCountry, oldCountry) 
            {
                setTimeout( function() 
                {
                    //function body here    
                }, 100);
            })
        }
    };  
}]);

$ rootScopeを使用する必要があるかどうかという、より哲学的な設計上の問題とは別に、上記の私のコードには、Mikeのソリューションから除外されていると思われる露骨に間違ったことが1つあります。あなたが私のようなもので、ディレクティブとコントローラーファイルを分離している場合は、次のようにコードを変更する必要があります。

app.directive('countrymap', ['$rootScope', function($rootScope) 
{
    return {
        link: function(scope, element, attrs) {
            $rootScope.$watch("countryMap", function (newCountry, oldCountry) 
            {
                setTimeout( function() 
                { 
                    //function body here
                }, 100);
            })
        }
    };  
}]);

それでも、もう1つのしつこい質問があります。同じ目標を達成できますかwithoutディレクティブで$ rootScopeを参照できますか?確かにできます。変更を$ rootScopeプロパティにブロードキャストして、すべての子スコープに変更を効果的に通知し、ディレクティブでこの変更を監視する必要があります。

コントローラ:

$rootScope.countryMap = 'thiscountry_map';
$rootScope.$broadcast( "countryMapChanged", $rootScope.countryMap );

指令:

app.directive('countrymapalt', [function() 
{
    return {
        link: function(scope, element, attrs) {
            scope.$on("countryMapChanged", function(event, map) 
            {
                setTimeout( function() 
                { 
                    //function body here
                }, 100);
            })
        }
    };  
}]);
3
user1991179

別の方法は、サービスを作成し、そのサービスに$ rootScopeおよびその他の関数にアクセスさせることです。私の環境のおかげでこうしました...

app.service('myService', function ($rootScope) 
{
    this.removeItem = function (el) 
    {
       console.log('rootScope: ',$rootScope);
       return true;
    }
});


app.directive('draggable', function($document,myService) 
{
   return function(scope, element, attr) 
   {
        myService.removeItem({id:1})
   }
});

可能であれば、最良の方法はマイクのソリューションです。そうでない場合は、私の解決策を試してください。

1
Philip Enc