2013-03-15 13 views
124

Próbuję sprawdzić, czy istnieje prosty sposób uzyskać dostęp do zakresu wewnętrznego kontrolera za pośrednictwem funkcji javascript zewnętrznego (całkowicie nieistotny do sterownika docelowego)angularjs dostęp do funkcji poza zakres od js

widziałem na kilka innych pytań tutaj

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

by odzyskać zakresu od elementu DOM, ale moje próby nie są obecnie uzyskując odpowiednie wyniki.

Oto jsfiddle: http://jsfiddle.net/sXkjc/5/

Jestem obecnie przeżywa przejście od zwykłego JS do kątowa. Głównym powodem, dla którego próbuję to osiągnąć, jest zachowanie nienaruszonego oryginalnego kodu biblioteki; oszczędzając potrzebę dodania każdej funkcji do kontrolera.

Jakieś pomysły na to, w jaki sposób mogę osiągnąć ten cel? Komentarze na temat powyższego skrzypiec są również mile widziane.

+0

FYI według Dokumenty używając '.scope()' wymaga dane diagnostyczne się włączyć ale [pomocą debugowania danych produkcji nie jest zalecane] (https://docs.angularjs.org/guide/production#disabling-debug-data) ze względu na szybkość. Poniższe rozwiązania wydają się krążyć wokół 'scope()' – rtpHarry

+0

@rtpHarry ma rację. Odpowiedzi poniżej, które wymagają użycia scope(), są przestarzałe. Zobacz moją odpowiedź tutaj http://stackoverflow.com/a/34078750/319302 –

Odpowiedz

209

Musisz użyć $scope.$apply(), jeśli chcesz wprowadzić jakiekolwiek zmiany wartości zakresu spoza formantów angularjs, takich jak obsługa zdarzeń jquery/javascript.

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

Demo: Fiddle

+0

Dzięki za odpowiedź. Próbowałem już Fiddle, ale nadal otrzymuję ten sam ciąg "You are great", nawet po kliknięciu "click me".Otrzymuję alert, ale nie zmianę łańcucha. Czy widzisz zmiany? – dk123

+0

@ dk123 wystąpił błąd skryptu sprawdź teraz –

+2

@ dk123 'kątowy.element (" # zakres ")' nie działa, chociaż 'kątowy.element ($ (" # zakres "))' działa, musisz jquery również –

26

Minęło trochę czasu odkąd wysłana na to pytanie, ale biorąc pod uwagę poglądy to wciąż wydaje się, tu jest inne rozwiązanie Doszedłem po ciągu tych ostatnich kilku miesięcy:

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

powyższy kod tworzy w zasadzie funkcję o nazwie safeApply że Calles funkcję $apply (jak wskazano w odpowiedzi na Arun) wtedy i tylko kątowe obecnie nie będzie przez etapie $digest. Z drugiej strony, jeśli Angular aktualnie trawi rzeczy, po prostu wykona tę funkcję taką, jaka jest, ponieważ wystarczy to do wysłania sygnału do Angular, aby wprowadzić zmiany.

Występują liczne błędy podczas próby użycia funkcji $apply, podczas gdy AngularJs jest obecnie na etapie $digest. Powyższy kod safeApply jest bezpiecznym opakowaniem, aby zapobiec takim błędom.

(uwaga: ja osobiście lubię rzucić w safeApply jako funkcja $rootScope celach convenience)

Przykład:

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

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

+1

Dlaczego działa funkcja safeApply? Wydaje się, że to, co mówisz, to "wykonaj funkcję samodzielnie, jeśli Angular jest w etapach $ apply lub $ digest, w przeciwnym razie użyj $ apply(), aby zastosować funkcję" .... Ale jeśli wykonasz tę funkcję samodzielnie .. .. w jaki sposób aktualizuje się jakieś modele? Wydaje się, że nie byłoby to korzystne zachowanie, chyba że coś się dzieje, o czym nie wiem. Czy jakiś mechanizm w Angularie przeprowadza ankietę w zakresie $ dla zmian, które mogły się bezpośrednio wydarzyć? – trusktr

+0

Plus, jeśli chcesz zabezpieczyć się przed tymi stanami, to uważam, że błąd metody $ apply(), która musi zostać naprawiona. – trusktr

+0

@trusktr Z tego, co rozumiem, wykonywanie funkcji normalnie jest przechwytywane przez kąt, jeśli funkcja zmienia dowolne modele, a więc kątowe aktualizuje je w następnym etapie trawienia. – dk123

13

możemy go po załadowany

zadzwonić

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"); 
    }); 
} 
7

To było dawno nie zadał to pytanie, ale tutaj jest odpowiedź, która nie wymaga jQuery:

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

Zaakceptowanych odpowiedź jest wielki. Chciałem spojrzeć na to, co dzieje się z zakresem kątowym w kontekście ng-repeat. Chodzi o to, że Angular utworzy podzakres dla każdego powtarzanego przedmiotu. Podczas wywoływania metody określonej na oryginalnym $scope, zachowuje ona swoją oryginalną wartość (z powodu zamknięcia javascript). Jednak nazwa this odnosi się do zakresu wywołującego/obiektu. To działa dobrze, o ile nie ma wątpliwości, kiedy $scope i this są takie same i kiedy są różne. HTH

Oto skrzypce który ilustruje różnicę: https://jsfiddle.net/creitzel/oxsxjcyc/

12

Innym sposobem na to jest:

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

Poszukując sposobów na to zrobić przez prawie 4 godziny, wreszcie rozwiązanie to rozwiązuje mój problem. Pan tylko uratował mój dzień! – ayushgp

+1

Nadal nie rozumiem, dlaczego ten komentarz nie jest najlepszą odpowiedzią. Po kopaniu internetu przez kilka dni, z frustracją i gniewem, w końcu to rozwiązało mój problem. Dziękuję @Charleston. Jesteś świetny, sir! – Rajkumar

+0

Eleganckie rozwiązanie wyraźnie, ale zwięźle wyjaśnione. Sława! – wloescher

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

dostępem wartość zakresu

Zakładamy, że programRow.StationAuxiliaryTime jest tablicą obiektu

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

Oto rozwiązanie wielokrotnego użytku: 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'; 
    }); 

}; 
1

Jestem nowicjuszem, więc przepraszam, jeśli jest złą praktyką. W oparciu o wybraną odpowiedź, zrobiłem tę funkcję:

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

używam to w ten sposób:

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

Przy okazji, przepraszam za mój angielski

2

Można też spróbować:

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

@ dk123 to również nie wymaga dawki JQuery. –

Powiązane problemy