Yalıtım kapsamına sahip bir yönergenin şablonundan $ rootScope'a neden erişilemiyor?


81

İzolasyon kapsamı ile yönergenin şablonu denetleyiciye ('Ctrl') $ rootScope değişkenine erişemiyor gibi görünüyor, ancak bu değişken, yönergenin denetleyicisinde görünüyor. Denetleyici ('Ctrl') $ kapsam değişkeninin yalıtım kapsamında neden görünmediğini anlıyorum.

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

Değişkene, izolat kapsamı olmadan erişilir - izolat kapsam satırı yorumlanarak görülebileceği gibi:

        // scope: {},

$ RootScope'u yönergeye ... enjekte etmeyi denediniz directive('myTemplate', function($rootScope) { ... })mi?
Marc Kline

@MarcKline Bunu denedim ve şansım yok.
camden_kid


1
Bir hizmeti kullanmanın amaçlarınız için yeterli olmamasının bir nedeni var mı?
Marc Kline

1
@Kalyan - Ben şahsen $ rootScope'un yalnızca olaylar için ve Factory'nin de yönergelere veri aktarımı için kullanılması gerektiğini düşünüyorum. Bunun bir nedeni, $ rootScope kullanmanın ideal olmayan global değişkenler kullanmak gibi olmasıdır. Ayrıca, bir Fabrika, daha sonraki bir tarihte genişletilebilecek iyi tanımlanmış bir sarmalayıcı olabilir.
camden_kid

Yanıtlar:


164

Bu yolu kullanarak deneyebilirsiniz $root.blah

Çalışma Kodu

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
Bunu başarmak istediğim şeyi 'çözdüğü' için cevap olarak işaretliyorum ('$ root' ya da bunun böyle kullanılabileceğini bilmiyordum). Ancak , Mark Kline'ın cevabının genellikle en iyi çözüm olduğunu söyleyebilirim.
camden_kid

5
inanılmaz! $ rootScope'un $ root'a dönüştüğünü bilmek oldukça kullanışlı, çok teşekkürler!
Cris R

Bu mükemmel, çünkü yapmam gereken şey rootScope'ta tanımlanan bir işleve erişmekti
Alfredo A.

İyi bir. Burada da çalışıyor. Neden $ rootScope yerine $ root'u açıklar mısınız? Ayrıca $ rootScope enjekte ettim, ancak işlev çağrısı sırasında tanımsız.
Unknown_Coder

32

Genel olarak, $rootScopedenetleyiciler ve yönergeler arasında paylaşmanız gereken değerleri saklamak için kullanmaktan kaçınmalısınız . JS'de globals kullanmak gibi. Bunun yerine bir hizmet kullanın:

Sabit (veya değer ... kullanımı benzerdir):

.constant('blah', 'blah')

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

Bir fabrika (veya hizmet veya sağlayıcı):

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

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

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

    return blah;
})

İşte Fiddle'ınızdan herhangi birini nasıl kullanabileceğinizi gösteren bir çatal


3
+1 Bunun için ve başarmaya çalıştığım şey için beni doğru yönü gösterdiğin için çok teşekkürler . Yorumumda belirtilen nedenle NidhishKrishnan'ın 'cevap' olarak kabul edilmesi gerektiğini düşünüyorum.
camden_kid

1
Kullanılmaları nadir olduğundan sabitlerin kullanım durumu için +1. Ayrıca $ rootScope kullanmama konusundaki not profesyonel bir ipucuydu.
Farzad YZ

23

1) $scopeDenetleyicinizdeki (Ctrl) ve yönerge denetleyicisindeki yalıtım kapsamı nedeniyle aynı kapsama başvurmuyor - Ctrl ve kapsam2'de kapsam1'e sahip olduğumuzu varsayalım yönergede.

2) için izole kapsamı scope2 yok prototypicallly devralan $rootScope; yani tanımlarsanız $rootScope.blah, kapsam2'de görme şansınız yoktur. .

3) Yönerge şablonunuzda erişebileceğiniz şey kapsam 2'dir

Özetleyecek olursam, işte miras şeması

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


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

1
Çok yararlı ama nidhishkrishnan'ın çözümü, bir şekilde rootScope değerlerini kullanmak gerekliyse işe yarıyor. Güzel bir hack.
Marc Kline

1
Peki, html'de $ rootScope değişkenlerini neden kullanamadığımı ($ root olmadan) yanıtlamak için mantıklı söylediniz, ancak $ kapsamlarını görmek için Batarang eklentisini kullandığımda, $ rootScope, tüm diğerlerinin üst $ kapsamıdır (yönergelerdeki yalıtılmış kapsam dahil). Ayrıca, açısal resmi belgelerden alınan tanım şöyle demiştir : "Her uygulamanın tek bir kök kapsamı vardır. Diğer tüm kapsamlar, kök kapsamın alt kapsamlarıdır" ( docs.angularjs.org/api/ng/service/$rootScope )
IsraGab

1

Bunun eski bir soru olduğunu biliyorum. Ancak, yalıtılmış kapsamın neden $ kök kapsamındaki özelliklere erişemeyeceği konusundaki araştırmamı tatmin etmedi.

Bu yüzden açısal kitaplığı kazdım ve buldum -

$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();
  }

Bu, yeni bir kapsam oluşturulduğunda açısal olarak adlandırılan işlevdir. Burada, herhangi bir izole kapsamın prototip olarak kök kapsamı miras almadığı açıktır. bunun yerine yeni kapsamda '$ root' özelliği olarak yalnızca rootcope eklenir. Dolayısıyla, rootcope'un özelliklerine yalnızca yeni yalıtılmış kapsamdaki $ root özelliğinden erişebiliriz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.