En este tip mostraré como comunicarse con módulos cargados dentro de una película Flex principal. Los módulos son pequeñas películas MXML que creamos para luego incorporar dentro de otro MXML principal, de igual manera que un componente pero en este caso se genera un archivo .SWF externo independiente, lo que resulta útil ya que podemos compartir módulos entre diferentes películas.
Para colocar un módulo dentro de una película principal existen dos opciones, y con una nos encontraremos un pequeño problema al intentar comunicarnos.
La primera forma es como si de un componente se tratase, osea definiríamos el namespace, por ejemplo, xmlns:modules="*", y lo colocaríamos con ese tag:
Código :
<modules:module id="modulo"/>
Si este módulo tuviese una función actionscript pública llamada setTexto(t:String); que le asignase el valor a una variable privada podríamos acceder a ella sin problema desde la película MXML principal.
Código :
private function setModuleText():void { modulo.setTexto("texto") }
Ahora bien, también podríamos haber cargado el módulo con el componente ModuleLoader. De esta manera hubiésemos enlazado directamente al archivo .SWF generado al publicar el módulo:
Código :
<mx:ModuleLoader id="modulo" url="module.swf"/>
Cargarlo de esta manera es útil ya que nos permite intercambiar un modulo por otro dentro del mismo componente reasignando el parámetro URL. Al enlazar directamente al SWF nos permite incorporar módulos generados desde otras películas, incluso desde otros servidores.
El problema es que al colocar el módulo con ModuleLoader nos saltará un error al intentar acceder a sus funciones públicas.
Error :
¿Cómo lo podemos solucionar? Deberemos hacer que ese módulo implemente una Interface que disponga de esa función pública a la que queremos acceder.
Crearíamos esta sencillo archivo de interface, al que llamaríamos IModule.as:
Código :
package { public interface IModule { function setTexto(t:String):void } }
Para hacer que el módulo implemente esta interface le incluiremos el parámetro en el tag de definición:
Código :
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" implements="IModule">
Y de esta manera deberemos asignar la definición de tipo a la instancia del módulo para llamar a la función que implementa la interface:
Código :
private function setModuleText():void { var mod:IModule = modulo.child as IModule; mod.setTexto("texto"); }
Ahora si tenemos acceso a las funciones públicas del módulo
Este es todo el código completo por si alguien quiere darle un vistazo:
module.mxml
Código :
<?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" implements="IModule"> <mx:Script> <![CDATA[ [Bindable] private var _texto:String; public function setTexto(t:String):void { _texto = t; } ]]> </mx:Script> <mx:Label verticalCenter="0" left="20" right="20" textAlign="center" id="textoInput" text="{_texto}"/> </mx:Module>
Main.mxml
Código :
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:modules="*" layout="absolute"> <mx:Script> <![CDATA[ private function setModuleText1():void { modulo1.setTexto("texto1") } private function setModuleText2():void { var mod:IModule = modulo2.child as IModule; mod.setTexto("texto2"); } ]]> </mx:Script> <mx:VBox horizontalCenter="0" verticalCenter="0" horizontalAlign="center"> <modules:module id="modulo1"/> <mx:ModuleLoader id="modulo2" url="module.swf"/> <mx:Button label="Button1" click="setModuleText1()"/> <mx:Button label="Button2" click="setModuleText2()"/> </mx:VBox> </mx:Application>
IModule.as
Código :
package { public interface IModule { function setTexto(t:String):void } }
¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.
Por Zah el 31 de Octubre de 2008
¿Habría que definirlas en la interface con getters y setters?
Por vanvanero el 31 de Octubre de 2008
Por vanvanero el 31 de Octubre de 2008
Por Zguillez el 31 de Octubre de 2008
Zah-blog :
¿Habría que definirlas en la interface con getters y setters?
Si, también con los settes y getters... Todo a lo que quieras acceder a de estar definido en la interface
Por Zguillez el 31 de Octubre de 2008
vanvanero-blog :
Más que complicado es más estricto.. ya que estas obligado a definir la interface publica del modulo aunque eso te hará tener los módulos más claros y más reutilizables..
Por Otaku RzO el 31 de Octubre de 2008
Por ingjuanfelipe el 16 de Junio de 2009
Yo tengo una aplicacion que funciona como shell, está me carga los modulos mediante un componente ModuleLoader pero estos componentes son .swf, cuando hago la declaracion de la interfaz IModule:
var mod:IModule = modulo2.child as IModule;
mod.setTexto("texto2");
me genera un error ya que no la declaro en ningúna parte, los .swf los estoy generando como proyectos independientes a mi shell, por lo tanto no tengo la interfaz por ningun lado y si me dá por pegar el archivo en mi proyecto aunque no genera error no me funciona, que estaré haciendo mal??.
Por David el 28 de Agosto de 2010
http://yakovfain.javadevelopersjournal.com/flex_best_practices_sketch_1_an_application_with_a_single_.htm
y aquí el ejemplo que plantean con el source code:
http://myflex.org/theriabook/SingleEventDemo/TestSingleEventWithModules.html
Por felipe el 25 de Septiembre de 2010
Saludos