versiones varios otro llamar funcion ejemplos controladores controlador javascript actionscript-3 externalinterface angularjs

javascript - otro - varios controladores angularjs



Llamar a AngularJS desde el código heredado (7)

Además de las otras respuestas. Si no desea acceder a un método en un controlador pero desea acceder al servicio directamente, puede hacer algo como esto:

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

Estoy usando AngularJS para construir controles HTML que interactúen con una aplicación Flex heredada. Todas las devoluciones de llamadas de la aplicación Flex se deben adjuntar a la ventana DOM.

Por ejemplo (en AS3)

ExternalInterface.call("save", data);

Llamará

window.save = function(data){ // want to update a service // or dispatch an event here... }

Desde dentro de la función de cambio de tamaño de JS me gustaría enviar un evento que un controlador pueda escuchar. Parece que crear un servicio es el camino a seguir. ¿Puedes actualizar un servicio desde fuera de AngularJS? ¿Puede un controlador escuchar eventos de un servicio? En un experimento (haga clic para violín) lo hice, parece que puedo acceder a un servicio, pero la actualización de los datos del servicio no se refleja en la vista (en el ejemplo, una <option> debe agregar a la <select> ).

¡Gracias!


Gracias a la publicación anterior, puedo actualizar mi modelo con un evento asíncrono.

<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>

Declaro mi modelo

function Filters($scope) { $scope.filters = []; }

Y actualizo mi modelo desde fuera de mi alcance

ws.onmessage = function (evt) { dictt = JSON.parse(evt.data); angular.element(document.getElementById(''control-panel'')).scope().$apply(function(scope){ scope.filters = dictt.filters; }); };


La interoperabilidad desde fuera de angular a angular es igual que la aplicación angular de depuración o la integración con una biblioteca de terceros.

Para cualquier elemento DOM, puedes hacer esto:

  • angular.element(domElement).scope() para obtener el alcance actual del elemento
  • angular.element(domElement).injector() para obtener el inyector de la aplicación actual
  • angular.element(domElement).controller() para obtener una retención de la instancia ng-controller .

Desde el inyector puede obtener acceso a cualquier servicio en la aplicación angular. Del mismo modo, desde el alcance puede invocar cualquier método que se le haya publicado.

Tenga en cuenta que cualquier cambio en el modelo angular o cualquier invocaciones de método en el alcance debe estar incluido en $apply() esta manera:

$scope.$apply(function(){ // perform any model changes or method invocations here on angular app. });


La mejor explicación del concepto que he encontrado se encuentra aquí: https://groups.google.com/forum/#!msg/angular/kqFrwiysgpA/eB9mNbQzcHwJ

Para ahorrarle el clic:

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


Misko dio la respuesta correcta (obviamente), pero algunos de nosotros novatos podemos necesitar que se simplifique aún más.

Cuando se trata de llamar al código AngularJS desde aplicaciones heredadas, piense en el código AngularJS como una "micro aplicación" existente dentro de un contenedor protegido en su aplicación heredada. No puede realizar llamadas directamente (por una buena razón), pero puede realizar llamadas remotas por medio del objeto $ scope.

Para usar el objeto $ scope, necesita obtener el control de $ scope. Afortunadamente, esto es muy fácil de hacer.

Puede usar la identificación de cualquier elemento HTML en su HTML "micro-app" de AngularJS para obtener el control de la aplicación AngularJS $ scope.

Como ejemplo, digamos que queremos llamar a un par de funciones dentro de nuestro controlador AngularJS como sayHi () y sayBye (). En el HTML AngularJS (ver) tenemos un div con el id "MySuperAwesomeApp". Puede usar el siguiente código, combinado con jQuery para obtener el control de $ scope:

var microappscope = angular.element($("#MySuperAwesomeApp")).scope();

Ahora puede llamar a sus funciones de código AngularJS por medio del manejador de alcance:

// we are in legacy code land here... microappscope.sayHi(); microappscope.sayBye();

Para hacer las cosas más convenientes, puede usar una función para tomar el control del alcance en cualquier momento que desee acceder a él:

function microappscope(){ return angular.element($("#MySuperAwesomeApp")).scope(); }

Sus llamadas se verían así:

microappscope().sayHi(); microappscope().sayBye();

Puedes ver un ejemplo de trabajo aquí:

http://jsfiddle.net/peterdrinnan/2nPnB/16/

También lo mostré en una presentación de diapositivas para el grupo Ottawa AngularJS (solo salte a las últimas 2 diapositivas)

http://www.slideshare.net/peterdrinnan/angular-for-legacyapps


Una forma más segura y efectiva, especialmente cuando los datos de depuración están desactivados, es usar una variable compartida para mantener una función de devolución de llamada. Su controlador angular implementa esta función para devolver sus componentes internos al código externo.

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

Generalizado como una directiva reutilizable:

Creé una directiva ''exposeScope'' que funciona de manera similar pero el uso es más simple:

<div ng-controller="myController" expose-scope="aVariableNameForThisScope"> <span expose-scope=''anotherVariableNameForTheSameScope" /> </div>

Esto almacena el alcance actual (que se le da a la función de enlace de la directiva) en un objeto global ''scopes'' que es un titular para todos los ámbitos. El valor proporcionado al atributo directivo se usa como el nombre de propiedad del alcance en este objeto global.

Vea la demostración here . Como mostré en la demostración, puede desencadenar eventos jQuery cuando el alcance se almacena y se elimina del objeto ''ámbitos'' globales.

<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>

Tenga en cuenta que no he probado on (''scopeDestroyed'') cuando el elemento real se elimina del DOM. Si no funciona, desencadenar el evento en el documento en sí en lugar del elemento puede ayudar. (ver el script app.js) en el demo plunker.


Sé que esta es una vieja pregunta, pero estaba buscando opciones para hacer esto recientemente, así que pensé en poner mis hallazgos aquí en caso de que sea útil para cualquiera.

En la mayoría de los casos, si existe la necesidad de que el código heredado externo interactúe con el estado de la interfaz de usuario o el funcionamiento interno de la aplicación, un servicio podría ser útil para abstraer esos cambios. Si un código externo está interactuando directamente con su controlador angular, componente o directiva, está conectando fuertemente su aplicación con su código heredado, lo cual es una mala noticia.

Lo que terminé usando en mi caso es una combinación de variables globales accesibles al navegador (es decir, ventanas) y manejo de eventos. Mi código tiene un motor de generación de formularios inteligentes que requiere salida JSON de un CMS para iniciar los formularios. Esto es lo que hice:

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

El servicio de esquema de formulario se crea utilizando un inyector angular como se esperaba:

angular.module(''myApp.services''). service(''FormSchemaService'', [''$window'' , FormSchemaService ])

Y en mis controladores: function () {''use strict'';

angular.module(''myApp'').controller(''MyController'', MyController); MyEncapsulatorController.$inject = [''$scope'', ''FormSchemaService'']; function MyController($scope, formSchemaService) { // using the already configured formSchemaService formSchemaService.buildForm();

Hasta ahora, esta es una programación puramente angular y orientada a servicios de JavaScript. Pero la integración heredada viene aquí:

<script type="text/javascript"> (function(app){ var conf = app.conf = { ''fields'': { ''field1: { // field configuration } } } ; app.dispatchEvent(new Event(''register-schema'')); })(window); </script>

Obviamente, cada enfoque tiene sus ventajas y desventajas. Las ventajas y el uso de este enfoque dependen de su UI. Los enfoques sugeridos anteriormente no funcionan en mi caso ya que mi esquema de formulario y el código heredado no tienen control ni conocimiento de los ámbitos angulares. Por lo tanto, la configuración de mi aplicación se basa en angular.element(''element-X'').scope(); podría potencialmente romper la aplicación si cambiamos los ámbitos. Pero si su aplicación tiene conocimiento del alcance y puede confiar en que no cambia a menudo, lo que se sugirió anteriormente es un enfoque viable.

Espero que esto ayude. Cualquier comentario también es bienvenido.