Wywołaj AngularJS z kodu źródłowego
Używam AngularJS do tworzenia kontrolek HTML, które współdziałają ze starszą aplikacją Flex. Wszystkie wywołania zwrotne z aplikacji Flex muszą być dołączone do okna DOM.
Na przykład (w AS3)
ExternalInterface.call("save", data);
Wywoła
window.save = function(data){
// want to update a service
// or dispatch an event here...
}
Z poziomu funkcji js resize chciałbym wysłać zdarzenie, które może usłyszeć kontroler. Wydaje się, że tworzenie usługi jest drogą do zrobienia. Czy możesz zaktualizować usługę spoza AngularJS? Czy kontroler może nasłuchiwać zdarzeń z usługi? W jednym eksperyment (kliknij po fiddle) {[12] } zrobiłem wygląda na to, że mogę uzyskać dostęp do usługi, ale aktualizacja danych usługi nie odbija się w widoku (w przykładzie należy dodać <option>
do <select>
).
7 answers
Interop z zewnątrz angular do angular jest taki sam jak debugowanie aplikacji angular lub integracja z biblioteką innych firm.
Dla dowolnego elementu DOM możesz to zrobić:
-
angular.element(domElement).scope()
Aby uzyskać bieżący zakres dla elementu -
angular.element(domElement).injector()
Aby pobrać aktualną aplikację injector -
angular.element(domElement).controller()
aby zdobyć instancjęng-controller
.
Należy pamiętać, że wszelkie zmiany w modelu kątowym lub jakiekolwiek wywołania metody na lunecie muszą być zawinięte w $apply()
w następujący sposób:
$scope.$apply(function(){
// perform any model changes or method invocations here on angular app.
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-09 01:29:49
Misko dał poprawną odpowiedź (oczywiście), ale niektórzy z nas nowicjuszy mogą potrzebować jej dalszego uproszczenia.
Jeśli chodzi o wywołanie kodu AngularJS z poziomu starszych aplikacji, pomyśl o kodzie AngularJS jako "mikro aplikacji" istniejącej w chronionym kontenerze w starszej aplikacji. Nie można wykonywać połączeń bezpośrednio (z bardzo ważnego powodu), ale można wykonywać połączenia zdalne przy pomocy obiektu $scope.
Aby użyć obiektu $ scope, musisz uzyskać obsługę $scope. Na szczęście jest to bardzo łatwe do zrobienia.
Możesz użyć identyfikatora dowolnego elementu HTML w Twojej aplikacji AngularJS "micro-app" HTML, aby uzyskać obsługę aplikacji AngularJS $scope.
Jako przykład, powiedzmy, że chcemy wywołać kilka funkcji w naszym kontrolerze AngularJS, takich jak sayHi () i sayBye (). W AngularJS HTML (view) mamy div o id "MySuperAwesomeApp". Możesz użyć następującego kodu, w połączeniu z jQuery, aby uzyskać obsługę $scope:
var microappscope = angular.element($("#MySuperAwesomeApp")).scope();
Teraz ty może wywoływać funkcje kodu AngularJS za pomocą uchwytu zakresu:
// we are in legacy code land here...
microappscope.sayHi();
microappscope.sayBye();
Aby uczynić coś wygodniejszego, możesz użyć funkcji, aby chwycić uchwyt zakresu w dowolnym momencie, aby uzyskać do niego dostęp:
function microappscope(){
return angular.element($("#MySuperAwesomeApp")).scope();
}
Twoje rozmowy wyglądałyby wtedy tak:
microappscope().sayHi();
microappscope().sayBye();
Możesz zobaczyć działający przykład tutaj:
Http://jsfiddle.net/peterdrinnan/2nPnB/16/
Pokazałem to również w pokazie slajdów dla grupy Ottawa AngularJS (po prostu przejdź do ostatnich 2 slajdy)
Http://www.slideshare.net/peterdrinnan/angular-for-legacyapps
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-29 15:45:20
Największe wyjaśnienie pojęcia, które znalazłem znajduje się tutaj: https://groups.google.com/forum/#! msg / angular/kqFrwiysgpA / eB9mNbQzcHwJ
Aby zapisać klikanie:
// get Angular scope from the known DOM element
e = document.getElementById('myAngularApp');
scope = angular.element(e).scope();
// update the model with a wrap in $apply(fn) which will refresh the view for us
scope.$apply(function() {
scope.controllerMethod(val);
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-09 19:34:58
Dzięki poprzedniemu wpisowi mogę zaktualizować mój model o Zdarzenie asynchroniczne.
<div id="control-panel" ng-controller="Filters">
<ul>
<li ng-repeat="filter in filters">
<button type="submit" value="" class="filter_btn">{{filter.name}}</button>
</li>
</ul>
</div>
Oświadczam, że mój model
function Filters($scope) {
$scope.filters = [];
}
I aktualizuję mój model spoza mojego zakresu
ws.onmessage = function (evt) {
dictt = JSON.parse(evt.data);
angular.element(document.getElementById('control-panel')).scope().$apply(function(scope){
scope.filters = dictt.filters;
});
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-08 01:43:15
Dalej do innych odpowiedzi. Jeśli nie chcesz uzyskać dostępu do metody w kontrolerze, ale chcesz uzyskać dostęp bezpośrednio do usługi, możesz zrobić coś takiego:
// Angular code* :
var myService = function(){
this.my_number = 9;
}
angular.module('myApp').service('myService', myService);
// External Legacy Code:
var external_access_to_my_service = angular.element('body').injector().get('myService');
var my_number = external_access_to_my_service.my_number
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-24 09:29:23
Bardziej bezpiecznym i wydajnym sposobem, zwłaszcza gdy dane debugowania są wyłączone, jest użycie współdzielonej zmiennej do przechowywania funkcji zwrotnej. Twój kontroler kątowy implementuje tę funkcję, aby przywrócić jego wewnętrzne elementy do zewnętrznego kodu.
var sharedVar = {}
myModule.constant('mySharedVar', sharedVar)
mymodule.controller('MyCtrl', [ '$scope','mySharedVar', function( $scope, mySharedVar) {
var scopeToReturn = $scope;
$scope.$on('$destroy', function() {
scopeToReturn = null;
});
mySharedVar.accessScope = function() {
return scopeToReturn;
}
}]);
Uogólniona jako dyrektywa wielokrotnego użytku:
Stworzyłem dyrektywę 'exposeScope', która działa w podobny sposób, ale użycie jest prostsze:
<div ng-controller="myController" expose-scope="aVariableNameForThisScope">
<span expose-scope='anotherVariableNameForTheSameScope" />
</div>
Przechowuje to bieżący zakres (który jest przypisany do funkcji link dyrektywy) w globalny obiekt "scopes", który jest uchwytem dla wszystkich zakresów. Wartość dostarczona do atrybutu dyrektywy jest używana jako nazwa właściwości zakresu w tym globalnym obiekcie.
Zobacz demo tutaj . Jak pokazałem w demo, możesz wywołać zdarzenia jQuery, gdy zakres jest przechowywany i usuwany z globalnego obiektu "zakresy".
<script type="text/javascript" >
$('div').on('scopeLinked', function(e, scopeName, scope, allScopes) {
// access the scope variable or the given name or the global scopes object
}.on('scopeDestroyed', function(e, scopeName, scope, allScopes) {
// access the scope variable or the given name or the global scopes object
}
</script>
Zauważ, że nie testowałem on ('scopeDestroyed'), gdy rzeczywisty element jest usuwany z DOM. Jeśli nie zadziała, wywołanie zdarzenia na może pomóc sam dokument zamiast elementu. (Zobacz aplikację.js) skrypt w wersji demo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-19 03:27:06
Wiem, że to stare pytanie, ale ostatnio patrzyłem na opcje, aby to zrobić, więc pomyślałem, że umieszczę moje ustalenia tutaj, na wypadek, gdyby było to przydatne dla kogokolwiek.
W większości przypadków, jeśli istnieje potrzeba zewnętrznego kodu starszego do interakcji ze stanem interfejsu użytkownika lub wewnętrznym działaniem aplikacji, Usługa może być przydatna do usunięcia tych zmian. Jeśli Zewnętrzny kod oddziałuje bezpośrednio z kontrolerem kątowym, komponentem lub dyrektywą, łączysz swój aplikacja mocno ze swoim starszym kodem, co jest złą wiadomością.
To, czego w moim przypadku użyłem, to połączenie globali dostępnych w przeglądarce (tj. okna) i obsługi zdarzeń. Mój kod ma inteligentny silnik generowania formularzy, który wymaga wyjścia JSON z CMS do inicjalizacji formularzy. Oto co zrobiłem:
function FormSchemaService(DOM) {
var conf = DOM.conf;
// This event is the point of integration from Legacy Code
DOM.addEventListener('register-schema', function (e) {
registerSchema(DOM.conf);
}, false);
// service logic continues ....
Usługa schematu formularza jest tworzona przy użyciu wtryskiwacza kątowego zgodnie z oczekiwaniami:
angular.module('myApp.services').
service('FormSchemaService', ['$window' , FormSchemaService ])
I w moich kontrolerach: funkcja () { "use strict";
angular.module('myApp').controller('MyController', MyController);
MyEncapsulatorController.$inject = ['$scope', 'FormSchemaService'];
function MyController($scope, formSchemaService) {
// using the already configured formSchemaService
formSchemaService.buildForm();
Do tej pory jest to czyste programowanie angular i javascript service oriented. Ale dziedzictwo integracji przychodzi tutaj:
<script type="text/javascript">
(function(app){
var conf = app.conf = {
'fields': {
'field1: { // field configuration }
}
} ;
app.dispatchEvent(new Event('register-schema'));
})(window);
</script>
Oczywiście każde podejście ma swoje zalety i wady. Zalety i zastosowanie tego podejścia zależy od twojego interfejsu użytkownika. Sugerowane wcześniej podejścia nie działają w moim przypadku, ponieważ mój schemat formularza i Kod źródłowy nie mają kontroli i wiedzy o zakresach kątowych. Dlatego konfigurowanie mojej aplikacji na podstawie angular.element('element-X').scope();
potencjalnie może złamać aplikację, jeśli zmienimy zakresy wokół. Ale jeśli aplikacja ma wiedzę na temat zakresu i może polegać na tym, że nie zmienia się często, to, co sugerowano wcześniej, jest realnym podejściem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-22 04:25:40