Js işlevinin dışındaki AngularJS erişim kapsamı


131

Bir denetleyicinin dahili kapsamına harici bir javascript işlevi aracılığıyla erişmenin basit bir yolu olup olmadığını görmeye çalışıyorum (hedef denetleyiciyle tamamen ilgisiz)

Burada birkaç başka soruda gördüm ki

angular.element("#scope").scope();

kapsamı bir DOM öğesinden alır, ancak girişimlerim şu anda uygun sonuç vermiyor.

İşte jsfiddle: http://jsfiddle.net/sXkjc/5/

Şu anda düz JS'den Angular'a geçiş yapıyorum. Bunu başarmaya çalışmamın ana nedeni, orijinal kitaplık kodumu olabildiğince sağlam tutmaktır; her işlevi denetleyiciye ekleme ihtiyacını ortadan kaldırıyor.

Bunu başarmak için nasıl gidebileceğime dair bir fikriniz var mı? Yukarıdaki kemanla ilgili yorumlar da memnuniyetle karşılanmaktadır.


Bilginize, belgelerin kullanımına göre .scope()Hata Ayıklama Verilerinin etkinleştirilmesi gerekir, ancak Hata Ayıklama Verilerinin üretimde kullanılması hız nedeniyle önerilmez . Aşağıdaki çözümler etrafında dönüyor gibi görünüyorscope()
rtpHarry

@rtpHarry haklı. Scope () kullanımını gerektiren aşağıdaki yanıtlar kullanımdan kaldırılmıştır. Cevabımı burada görün stackoverflow.com/a/34078750/319302
Cagatay Kalan

Yanıtlar:


223

$ Kapsam kullanmanız gerekiyor . $ Apply ()Jquery / javascript olay işleyicisi gibi angularjs'nin denetimi dışındaki bir kapsam değerinde değişiklik yapmak istiyorsanız, .

function change() {
    alert("a");
    var scope = angular.element($("#outer")).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}

Demo: Keman


2
@ dk123 angular.element("#scope")çalışmıyor, ancak angular.element($("#scope"))çalışıyor, ayrıca jquery'ye de sahip olmanız gerekiyor
Arun P Johny

1
Bir süredir biliyorum ama umarım bazıları bana bu konuda cevap verebilir ... Neden var kapsam = angular.element ($ ("# dış")). Kapsam (); değişiklik işlevi içinde beyan edilmeli mi? Onu küresel alana taşırsam, olmaz mı?
Marc M.

1
@MarcM. Angular'ın skop rekreasyonuyla ilgisi olduğunu düşünüyorum. Değişiklik işlevini kullandığınız zamana kadar, genel değişkenin işaret ettiği önceki kapsam artık mevcut olmayabilir (yeniden oluşturma nedeniyle).
dk123

1
angular.element ($ ( "div [ng kontrol cihazı = 'myCtrl']")) kapsamı (.); div öğesinde ek #outer'dan daha iyidir, sanırım
wyverny

1
Bunu yaptığımızda kapsam () tanımsız alır: $ compileProvider.debugInfoEnabled (false); açısal olarak. Öyleyse debuginfoEnabled false ile çalışmasını nasıl sağlayabiliriz?
Agnosco

26

Bu soruyu göndereli epey zaman oldu, ancak bunun hala elde ettiği görüşleri göz önünde bulundurarak, işte son birkaç aydır karşılaştığım başka bir çözüm:

$scope.safeApply = function( fn ) {
    var phase = this.$root.$$phase;
    if(phase == '$apply' || phase == '$digest') {
        if(fn) {
            fn();
        }
    } else {
        this.$apply(fn);
    }
};

Yukarıdaki kod temelde adında bir işlev oluşturur safeApplycalles o $apply(Arun yanıtında belirtildiği gibi) işlevi yalnızca Eğik anda eğer gerçekleşmiyorsa$digest sahnede. Öte yandan, Angular şu anda bir şeyleri sindiriyorsa , işlevi olduğu gibi yerine getirecektir, çünkü bu, değişiklikleri yapmak için Angular'a sinyal göndermek için yeterli olacaktır.

$applyAngularJs şu anda $digestaşamasındayken işlevi kullanmaya çalışırken çok sayıda hata oluşur . Yukarıdaki safeApplykod, bu tür hataları önlemek için güvenli bir paketleyicidir.

(not: Ben şahsen kolaylık sağlamak için safeApplybir işlevi olarak girmeyi seviyorum $rootScope)

Misal:

function change() {
    alert("a");
    var scope = angular.element($("#outer")).scope();
    scope.safeApply(function(){
        scope.msg = 'Superhero';
    })
}

Demo: http://jsfiddle.net/sXkjc/227/


1
SafeApply işleviniz neden çalışıyor? Görünüşe göre, "Angular $ apply veya $ sindirme aşamasındaysa işlevi kendi başına çalıştır, aksi takdirde işlevi uygulamak için $ apply () kullan" ... Ama işlevi kendi başına çalıştırırsan .. .. bu herhangi bir modeli nasıl günceller? Bilmediğim bir şey olmadıkça, bu pek uygun bir davranış olmayacak gibi görünüyor. Angular'daki bazı mekanizmalar, doğrudan başına gelmiş olabilecek değişiklikler için $ kapsamını sorguluyor mu ???
trusktr

Ayrıca, bu durumlara karşı koruma sağlamanız gerekiyorsa, o zaman $ apply () yönteminde düzeltilmesi gereken bir hata olduğunu düşünürdüm.
trusktr

@trusktr Anladığım kadarıyla, işlev herhangi bir modeli değiştirdiğinde ve dolayısıyla bir sonraki özet aşamasında açısal olarak güncellerse, işlevi normal olarak yürütmek açısal olarak yakalanır.
dk123

@trusktr Normal $ apply () güvenlik önlemleri olmadan uygulanabilirse, daha iyi bir şey olmayacağını kabul ediyorum. Esasında, safeApply'nin tek amacı $ apply () hatalarına karşı koruma sağlamaktır. Bunun bildirilen bir sorun olup olmadığından ve şimdi düzeltildiğinden mi yoksa hala devam eden bir sorun mu olduğundan emin değilim.
dk123

1
Sırf tökezlediğim için: github.com/angular/angular.js/wiki/When-to-use-$scope.$apply () . _ İf (! $ Kapsam. $$ faz) $ kapsam yapıyorsanız, bunun nedeni çağrı yığınında yeterince yüksek olmamanızdır._
scheffield

17

Bunu yapmanın başka bir yolu şudur:

var extScope;
var app = angular.module('myApp', []);
app.controller('myController',function($scope, $http){
    extScope = $scope;
})
//below you do what you want to do with $scope as extScope
extScope.$apply(function(){
    extScope.test = 'Hello world';
})

1
Hala bu yorumun neden bunun için en iyi cevap olmadığını anlamıyorum. Hayal kırıklığı ve öfkeyle birkaç gün interneti kazdıktan sonra nihayet sorunumu çözen buydu. Teşekkürler @Charleston. Harikasınız efendim!
Rajkumar

13

yüklendikten sonra arayabiliriz

http://jsfiddle.net/gentletech/s3qtv/3/

<div id="wrap" ng-controller="Ctrl">
    {{message}}<br>
    {{info}}
    </div>
    <a  onClick="hi()">click me </a>

    function Ctrl($scope) {
        $scope.message = "hi robi";
        $scope.updateMessage = function(_s){
            $scope.message = _s;    
        };
    }

function hi(){
    var scope = angular.element(document.getElementById("wrap")).scope();
        scope.$apply(function() {
        scope.info = "nami";
        scope.updateMessage("i am new fans like nami");
    });
}

8

Bu soruyu sormayalı uzun zaman oldu, ama işte jquery gerektirmeyen bir cevap:

function change() {
    var scope = angular.element(document.querySelector('#outside')).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}

3

İşte yeniden kullanılabilir bir çözüm: http://jsfiddle.net/flobar/r28b0gmq/

function accessScope(node, func) {
    var scope = angular.element(document.querySelector(node)).scope();
    scope.$apply(func);
}

window.onload = function () {

    accessScope('#outer', function (scope) {
        // change any property inside the scope
        scope.name = 'John';
        scope.sname = 'Doe';
        scope.msg = 'Superhero';
    });

};

2

Şunları da deneyebilirsiniz:

function change() {
    var scope = angular.element( document.getElementById('outer') ).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}

@ dk123 bu doz ayrıca JQuery gerektirmez.
harish sharma

1

Kabul edilen cevap harika. Açısal kapsama bağlamında ne olduğuna bakmak istedim ng-repeat. Mesele şu ki, Angular tekrarlanan her öğe için bir alt kapsam oluşturacak. Orijinalde tanımlanan bir yöntemi çağırırken $scope, orijinal değerini korur (javascript kapanması nedeniyle). Ancak, thisçağıran kapsamı / nesneyi ifade eder. Bu çok uzun zaman açık olduğunuz gibi iyi çalışıyor $scopeve thisaynıdır ve bunlar farklı olduğunda. hth

İşte farkı gösteren bir keman: https://jsfiddle.net/creitzel/oxsxjcyc/


1

Ben acemiyim, çok üzgünüm eğer kötü bir pratikse. Seçilen cevaba göre şu işlevi yaptım:

function x_apply(selector, variable, value) {
    var scope = angular.element( $(selector) ).scope();
    scope.$apply(function(){
        scope[variable] = value;
    });
}

Bunu şu şekilde kullanıyorum:

x_apply('#fileuploader', 'thereisfiles', true);

Bu arada, ingilizcem için özür dilerim


0
<input type="text" class="form-control timepicker2" ng-model='programRow.StationAuxiliaryTime.ST88' />

kapsam değerine erişim

programRow.StationAuxiliaryTime'ın bir nesne dizisi olduğunu varsayın

 $('.timepicker2').on('click', function () 
    {
            var currentElement = $(this);

            var scopeValues = angular.element(currentElement).scope();
            var model = currentElement.attr('ng-model');
            var stationNumber = model.split('.')[2];
            var val = '';
            if (model.indexOf("StationWaterTime") > 0) {
                val = scopeValues.programRow.StationWaterTime[stationNumber];
            }
            else {
                val = scopeValues.programRow.StationAuxiliaryTime[stationNumber];
            }
            currentElement.timepicker('setTime', val);
        });

0

$ Apply işlevinde yerleşik Angular Js'yi denetleyici işlevi dışındaki erişim kapsam değişkenlerine veya işlevlerine kullanmamız gerekir .

Bu iki şekilde yapılabilir :

| * | Yöntem 1: Kimliği Kullanma:

<div id="nameNgsDivUid" ng-app="">
    <a onclick="actNgsFnc()"> Activate Angular Scope</a><br><br>
    {{ nameNgsVar }}
</div>

<script type="text/javascript">

    var nameNgsDivVar = document.getElementById('nameNgsDivUid')

    function actNgsFnc()
    {
        var scopeNgsVar = angular.element(nameNgsDivVar).scope();
        scopeNgsVar.$apply(function()
        {
            scopeNgsVar.nameNgsVar = "Tst Txt";
        })
    }

</script>

| * | Yöntem 2: ng-denetleyicinin başlangıcını kullanma:

<div ng-app="nameNgsApp" ng-controller="nameNgsCtl">
    <a onclick="actNgsFnc()"> Activate Angular Scope</a><br><br>
    {{ nameNgsVar }}
</div>

<script type="text/javascript">

    var scopeNgsVar;
    var nameNgsAppVar=angular.module("nameNgsApp",[])
    nameNgsAppVar.controller("nameNgsCtl",function($scope)
    {
        scopeNgsVar=$scope;
    })

    function actNgsFnc()
    {
        scopeNgsVar.$apply(function()
        {
            scopeNgsVar.nameNgsVar = "Tst Txt";
        })
    }

</script>
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.