Comunidad de diseño web y desarrollo en internet

Comunicación entre módulos cargados con ModuleLoader en Flex

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 :

1061: Llamada a un método setTexto posiblemente no definido mediante una referencia con tipo estático mx.modules:ModuleLoader.


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

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate