AngularJS - Alt kapsama erişim


110

Aşağıdaki denetleyicilerim varsa:

function parent($scope, service) {
    $scope.a = 'foo';

    $scope.save = function() {
        service.save({
            a:  $scope.a,
            b:  $scope.b
        });
    }
}

function child($scope) {
    $scope.b = 'bar';
}

İzin uygun yolu nedir parentokumak bdışında child? O tanımlamak gerekli ise bde parent, bu anlam yanlış olduğunu varsayarak yapmak olmaz bilgili bir şey açıklayan bir özelliktir childdeğil parent?

Güncelleme: birden fazla çocuk olsaydı, bu konuda daha fazla düşünmek bonun için çakışma oluşturacak parenthangi balmak için. Benim sorum kalıntıları, erişime uygun yolu nedir bdan parent?


1
Ayrıca, şunu okuduğunuzdan emin olun: stackoverflow.com/questions/14049480/… angularJS'de kapsamlara ve kalıtıma çok iyi ve derinlemesine bir genel bakış.
Martijn

Yanıtlar:


162

AngularJS'deki kapsamlar prototip kalıtımı kullanır, bir çocuk kapsamındaki bir özelliği ararken, yorumlayıcı prototip zincirini çocuktan başlayarak arar ve mülkü bulana kadar ebeveynlere devam eder, tersi değil.

Vojta'nın konuyla ilgili yorumlarını kontrol edin https://groups.google.com/d/msg/angular/LDNz_TQQiNE/ygYrSvdI0A0J

Özetle: Alt kapsamlara bir üst kapsamdan erişemezsiniz.

Çözümleriniz:

  1. Ebeveynlerdeki özellikleri tanımlayın ve bunlara çocuklardan erişin (yukarıdaki bağlantıyı okuyun)
  2. Durumu paylaşmak için bir hizmet kullanın
  3. Verileri etkinliklerden geçirin. $emitkök kapsamı kadar olayları üst öğelere gönderir ve $broadcastolayları aşağı doğru gönderir. Bu, şeyleri anlamsal olarak doğru tutmanıza yardımcı olabilir.

8
Ayrıca, $ emit ve $ yayın arasındaki fark, $ emit'in iptal edilebilir olduğu ve $ yayın yapmadığı durumdur.
Azri Jamil

Muhtemelen alt kapsamı almak isteyeceğiniz yerlerden biri, birim testi yönergeleridir. Transcluded bir yönergeniz varsa, kapsam, öğeyi derlemek için kullanılan kapsamın bir alt öğesidir. Test için derlenmiş direktifin kapsamına erişmek zordur.
pmc

Teşekkürler. Başka bir seçenek, localStoragegibi bir bağımlılıkla olabilir ngStorage.
Akash

81

Jm-'nin cevabı bu durumu ele almanın en iyi yolu olsa da, ileride başvurmak için kapsamın $$ childHead, $$ childTail, $$ nextSibling ve $$ prevSibling üyelerini kullanarak alt kapsamlara erişmek mümkündür. Bunlar belgelenmediğinden önceden haber verilmeksizin değiştirilebilir, ancak kapsamları gerçekten geçmeniz gerekiyorsa oradalar .

// get $$childHead first and then iterate that scope's $$nextSiblings
for(var cs = scope.$$childHead; cs; cs = cs.$$nextSibling) {
    // cs is child scope
}

Vaktini boşa harcamak


49

Bunu deneyebilirsiniz:

$scope.child = {} //declare it in parent controller (scope)

sonra alt denetleyicide (kapsam) ekleyin:

var parentScope = $scope.$parent;
parentScope.child = $scope;

Artık ebeveyn, çocuğun kapsamına erişebilir.


1
Çok temiz ve anlaşılır. Buna ek olarak, hiçbir bağlayıcılığın olmadığını fark edin, bu yüzden bunu parentScope.child'in yukarısında olduğu gibi ilan ettiğinizde o anda childs kapsamını tutuyor. Bunu çözmek için $ kapsam ekleyebilirsiniz. $ Watch (function () {parentScope.child = $ kapsam}); böylece her özetten sonra yeni kapsamı üst öğeye doğru iter. Üst uçta, html'deki görseller için alt kapsamlardan herhangi birini kullanıyorsanız, alt değişkenine bir izleme eklemeniz ve kapsamı şu şekilde güncellemesini söylemeniz gerekir: $ kapsam. $ Watch ('child', function ( ) {$ kapsam. $ evalAsync ();}); . Umarım bu birine biraz zaman kazandırır!
IfTrue

2
@IfTrue Bir $ watch () gerekli olmadığına inanıyorum. Bunlar nesnelerdir ve referansla geçerler.
Swanidhi

2
@Swanidhi = Ne demek istediğinizi anlıyorum ve ben de öyle düşündüm ama yorumu yazarken deney yaparken işe yaramadı. Ne olursa olsun, bunu yapmaktan yaymaya / yayına geçtim.
IfTrue

1
Bunu Type Script'te nasıl yapabilirim?
Ather

Benim için en iyi cevap !! Javascript'te referans olarak değerlendirilen nesnelerin en iyi örneği
Vikas Gautam

4

Olası bir geçici çözüm, bir init işlevi kullanarak üst denetleyiciye alt denetleyiciyi enjekte etmektir.

Olası uygulama:

<div ng-controller="ParentController as parentCtrl">
   ...

    <div ng-controller="ChildController as childCtrl" 
         ng-init="ChildCtrl.init()">
       ...
    </div>
</div>

Nerede ChildControllersahipsin:

app.controller('ChildController',
    ['$scope', '$rootScope', function ($scope, $rootScope) {
    this.init = function() {
         $scope.parentCtrl.childCtrl = $scope.childCtrl;
         $scope.childCtrl.test = 'aaaa';
    };

}])

Yani şimdi ParentControllerkullanabilirsiniz:

app.controller('ParentController',
    ['$scope', '$rootScope', 'service', function ($scope, $rootScope, service) {

    this.save = function() {
        service.save({
            a:  $scope.parentCtrl.ChildCtrl.test
        });
     };

}])

Önemli:
Düzgün çalışması için yönergeyi kullanmanız ve html'de yaptığım gibi ng-controllerher bir denetleyiciyi yeniden adlandırmanız gerekir as.

İpuçları: İşlem sırasında
krom eklenti denetçisini kullanın . Ağacı anlamanıza yardımcı olacak.


3

$ Emit ve $ yayın kullanarak (yukarıdaki yorumlarda walv tarafından belirtildiği gibi)

Bir olayı yukarı doğru tetiklemek için (çocuktan ebeveyne)

$scope.$emit('myTestEvent', 'Data to send');

Bir olayı aşağı doğru tetiklemek için (ebeveynden çocuğa)

$scope.$broadcast('myTestEvent', {
  someProp: 'Sending you some data'
});

ve sonunda dinlemek

$scope.$on('myTestEvent', function (event, data) {
  console.log(data);
});

Daha fazla ayrıntı için: - https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Zevk almak :)


1

Evet, alt denetleyicideki değişkenleri üst denetleyicideki değişkenlere atayabiliriz. Bu olası bir yoldur:

Genel Bakış: Aşağıdaki kodun ana amacı, alt denetleyicinin $ kapsam. Değişkenini üst denetleyicinin $ kapsamına atamaktır.

Açıklama: İki denetleyici vardır. Html'de, üst denetleyicinin alt denetleyiciyi içerdiğine dikkat edin. Bu, üst denetleyicinin alt denetleyiciden önce yürütüleceği anlamına gelir. Bu nedenle, önce setValue () tanımlanacak ve ardından kontrol alt denetleyiciye gidecek. $ kapsam.variable "alt" olarak atanacak. Daha sonra bu alt kapsam, üst denetleyicinin işlevine bir argüman olarak aktarılır, burada $ kapsam.assign, değeri "alt" olarak alacaktır.

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script type="text/javascript">
    var app = angular.module('myApp',[]);

    app.controller('child',function($scope){
        $scope.variable = "child";
        $scope.$parent.setValue($scope);
    });

    app.controller('parent',function($scope){
        $scope.setValue = function(childscope) {
            $scope.assign = childscope.variable;
        }
    });

</script>
<body ng-app="myApp">
 <div ng-controller="parent">
    <p>this is parent: {{assign}}</p>
    <div ng-controller="child">
        <p>this is {{variable}}</p>
    </div>
 </div>
</body>
</html>
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.