Estoy usando AngularJS para crear controles HTML que interactúan con una aplicación Flex heredada. Todas las devoluciones de llamada 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 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. ¿Se puede actualizar un servicio desde fuera de AngularJS? ¿Puede un controlador escuchar eventos de un servicio? En un experimento (haga clic para violín) que 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, se <option>
debe agregar a <select>
).
¡Gracias!
var injector = angular.injector(['ng', 'MyApp']);
. Hacer esto le dará un contexto completamente nuevo y un duplicadomyService
. Eso significa que terminará con dos instancias del servicio y el modelo y agregará datos al lugar equivocado. En su lugar, debe apuntar a un elemento dentro de la aplicación utilizandoangular.element('#ng-app').injector(['ng', 'MyApp'])
. En este punto, puede usar $ apply para ajustar los cambios del modelo.Respuestas:
La interoperabilidad desde fuera de angular a angular es igual a la depuración de la aplicación angular o la integración con la biblioteca de terceros.
Para cualquier elemento DOM puede hacer esto:
angular.element(domElement).scope()
para obtener el alcance actual del elementoangular.element(domElement).injector()
para obtener el inyector de la aplicación actualangular.element(domElement).controller()
para obtener lang-controller
instancia.Desde el inyector puede obtener cualquier servicio en aplicaciones angulares. 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 invocación de método en el alcance deben incluirse de
$apply()
esta manera:fuente
[ng-app]
nodo raíz parece estar al revés cuando ya tengo una referencia al Módulo ...angular.element(document.getElementById(divName)).scope()
, pero no puedo invocar ninguna función, simplemente devuelve "indefinido" en la consola.Misko dio la respuesta correcta (obviamente), pero algunos de nosotros, los 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 muy buena razón), pero puede realizar llamadas remotas a través del objeto $ scope.
Para usar el objeto $ scope, necesita obtener el identificador de $ scope. Afortunadamente esto es muy fácil de hacer.
Puede usar la identificación de cualquier elemento HTML dentro de su HTML de "micro-aplicación" AngularJS para obtener el identificador 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 AngularJS HTML (vista) tenemos un div con el id "MySuperAwesomeApp". Puede usar el siguiente código, combinado con jQuery para obtener el identificador de $ scope:
Ahora puede llamar a sus funciones de código AngularJS a través del identificador de alcance:
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:
Sus llamadas se verían así:
Puedes ver un ejemplo de trabajo aquí:
http://jsfiddle.net/peterdrinnan/2nPnB/16/
También mostré esto 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
fuente
<input type="button" onclick="angular.element(this).scope().edit.delete();" value="delete">
La mejor explicación del concepto que he encontrado se encuentra aquí: https://groups.google.com/forum/#!msg/angular/kqFrwiysgpA/eB9mNbQzcHwJ
Para ahorrarte el clic:
fuente
id
en el elemento HTML superior y luego hacerdocument.getElementById()
esa identificación. Esto le da acceso al alcance de ese controlador. métodos / propiedades, etc ... simplemente poniendo un punto fino en el comentario de goosemanjack.Más allá 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:
fuente
Gracias a la publicación anterior, puedo actualizar mi modelo con un evento asincrónico.
Declaro mi modelo
Y actualizo mi modelo desde fuera de mi alcance
fuente
Una forma más segura y eficaz, 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.
Generalizado como directiva reutilizable:
Creé una directiva 'exposeScope' que funciona de manera similar pero el uso es más simple:
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 el titular de todos los ámbitos. El valor proporcionado al atributo de directiva se usa como el nombre de propiedad del ámbito en este objeto global.
Vea la demostración aquí . Como mostré en la demostración, puede activar eventos jQuery cuando el ámbito se almacena y se elimina del objeto global 'ámbitos'.
Tenga en cuenta que no he probado el encendido ('scopeDestroyed') cuando el elemento real se elimina del DOM. Si no funciona, puede ser útil activar el evento en el documento en lugar del elemento. (vea el script app.js) en el demo plunker.
fuente
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 alguien.
En la mayoría de los casos, si existe la necesidad de un código heredado externo para interactuar 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 interactúa directamente con su controlador angular, componente o directiva, está acoplando su aplicación en gran medida con su código heredado, lo cual es una mala noticia.
Lo que terminé usando en mi caso, es una combinación de globales accesibles para el navegador (es decir, ventana) y manejo de eventos. Mi código tiene un motor de generación de formularios inteligente que requiere la salida JSON de un CMS para iniciar los formularios. Esto es lo que he hecho:
El servicio de esquema de formulario se crea utilizando un inyector angular como se esperaba:
Y en mis controladores: function () {'use estricto';
Hasta ahora, esta es una programación puramente angular y orientada al servicio de JavaScript. Pero la integración heredada viene aquí:
Obviamente, cada enfoque tiene sus méritos e inconvenientes. Las ventajas y el uso de este enfoque dependen de su interfaz de usuario. Los enfoques sugeridos anteriormente no funcionan en mi caso, ya que mi esquema de formulario y mi código heredado no tienen control ni conocimiento de los ámbitos angulares. Por lo tanto, configurar mi aplicación en función
angular.element('element-X').scope();
podría romper la aplicación si cambiamos los ámbitos. Pero si su aplicación tiene conocimiento del alcance y puede confiar en que no cambiará con frecuencia, lo que se sugiere anteriormente es un enfoque viable.Espero que esto ayude. Cualquier comentario también es bienvenido.
fuente