8 Replies Latest reply on Feb 20, 2011 8:51 PM by guns3218

    Is it possible to call module component's function through interface function

    guns3218

      Hi,

       

           I see this in the livedocs.

       

      "In general, if you want to set properties on controls in the module by using external values, you should create variables that are bindable. You then set the values of those variables in the interface’s implemented methods. If you try to set properties of the module’s controls directly by using external values, the controls might not be instantiated by the time the module is loaded and the attempt to set the properties might fail."

       

           I have an extended component in a module. I need to call that component's funcion from the interface function. i.e My main appication call the interface funcion, and that interface funcion has to call the component's funcion. Is it possible. I get error that the component is null, if I try this. Is there any way to do this.

       

           Thanks in advance.

        • 1. Re: Is it possible to call module component's function through interface function
          Flex harUI Adobe Employee

          It is possible.  You might dispatch an event when the component is ready.

          • 2. Re: Is it possible to call module component's function through interface function
            guns3218 Level 1

            Thanks for the reply. The function will be called only on user's action.I see the component visually.  Still not able to access it. is there something else, to make the component ready.

             

            assume that 'myComp' is my compoenent in module, and test() is a function in that, and intFunc() is the implemented function in module.

             

            I want to do this.

             

            public function intFunc():void {

                 myComp.test();
            }

             

            The intFunc will be called from main application when the user does some action.

             

            From my understaning you are saying to dispatch event from myComp, when it is ready. Please let me know how can I identify the component is ready. using creationComplete?. creationComplete means the component is visually created right?

            • 4. Re: Is it possible to call module component's function through interface function
              guns3218 Level 1

              I accomplished this, by dispatching a event from the module, and handling it in the module itself. In the handler I am able to access the component. However it is possible only when I use ModuleLoader. I tried the same using ModuleManager. It didnt work. I am adding the listener in creationComplete event. The event was triggered properly. But the listener was not invoked.

               

              Below is the TestModule i used. In this setLabel is the implemented function.

               

              <mx:Module xmlns:fx="http://ns.adobe.com/mxml/2009"
                         xmlns:s="library://ns.adobe.com/flex/spark" implements="TestInterface" creationComplete="onCreate()"
                         xmlns:mx="library://ns.adobe.com/flex/mx" layout="absolute" width="400" height="300">
                  <fx:Script>
                      <![CDATA[
                          [Bindable] public var labelText:String = 'Initial Text';
                          public function onCreate():void {               
                              this.addEventListener("test",testListener);
                          }
                          public function setLabel(s:String):void {

                              trace(getQualifiedClassName(parentDocument));
                              this.labelText = s;       
                              triggerEvent();
                          }
                          public function triggerEvent():void {
                              trace('triggering event');
                              dispatchEvent(new Event("test",true));
                          }
                          public function testListener(event:Event):void {
                              trace('event caught');
                              trace(moduleLabel.text);
                          }
                      ]]>
                  </fx:Script>
                  <fx:Declarations>
                      <!-- Place non-visual elements (e.g., services, value objects) here -->
                  </fx:Declarations>
                  <mx:Label id="moduleLabel" text="{labelText}"/>
              </mx:Module>

               

              With ModuleLoader I get the following output in console, when the setLabel function is called

               

              ModuleTest
              triggering event
              event caught
              test

               

              With ModuleManger,I get the following output. The event listener is not invoked.

               

              null
              triggering event

               

              Also while trying different options, in between I tried using parentDocument. I added the below line in the interface function.

               

              trace(getQualifiedClassName(parentDocument));

               

              This line printed the correct parent class name, while using ModuleLoader. But printed null with ModuleManager.

               

              Following are the functions in main application to load the module using module manager.

               

                          public function onCreate():void {
                              loadTestModule();
                          }
                          public function loadTestModule():void {       
                              var url:String = '';
                              url += 'TestModule.swf';
                              modInfo = ModuleManager.getModule(url);
                              modInfo.addEventListener(ModuleEvent.ERROR,moduleReady);
                              modInfo.addEventListener(ModuleEvent.READY,moduleReady);
                              modInfo.load(null, null, null, moduleFactory);
                          }
                          public function moduleReady(event:ModuleEvent):void {               
                              if (event.type == ModuleEvent.ERROR) {
                                  trace(event.errorText);
                              }
                              if (event.type == ModuleEvent.READY) {
                                  mod = modInfo.factory.create() as TestInterface;
                                  var el:IVisualElement = modInfo.factory.create() as IVisualElement;
                                  this.addElement(el);                   
                              }
                          }

               

              Am I missing something when I use ModuleManager.

              • 5. Re: Is it possible to call module component's function through interface function
                FM_Flame Level 1

                Hi,

                 

                I guess in you example above you forgot to paste the calling of the interface function with the "test" text.

                 

                I don't have the time to test your case so I could be wrong about this but I hope it helps.

                 

                But anyway looks normal the output that you give cause at the time the module is ready it doesn't mean that it has been created as well as his child elements.

                 

                And so you call the interface function on ready where nothing is created yet and you get "null" for the class (not created yet) and "triggering event", which will not trigger anything since the module hasn't been created yet, which means the listener is not yet registered.

                 

                Add a listener to the module ("el") for creationComplete and then call the interface function if you want your other traces to show up as well.

                 

                But still, I think that in both cases you should be able to see the text since the [Bindable] labelText should be working correctly and you can set it's value before the module and it's elements are created and when they are, they will get that value.

                 

                I am not sure why the moduleLoader gives you different results, I don't have your code for it, but it shouldn't be acting any different.

                 

                You can also post you sdk version with witch you are testing for people looking at your problem to be able to reproduce.

                 

                F

                • 6. Re: Is it possible to call module component's function through interface function
                  guns3218 Level 1

                  I understand that, you are saying by the time the interface function  is called the module and its children are not completely created.  Actually the call of interface funcion is triggered by a button click.  Here is the full application code.

                   

                  <?xml version="1.0" encoding="utf-8"?>
                  <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                                  xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="onCreate()"
                                  xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
                       <fx:Script>
                           <![CDATA[
                               import mx.events.ModuleEvent;
                               import mx.modules.IModuleInfo;
                               import mx.modules.ModuleManager;
                               public var modInfo:IModuleInfo;
                               public var mod:TestInterface;
                               import mx.core.IVisualElement;           
                              
                               public function onCreate():void {
                                   loadTestModule();
                               }
                               public function loadTestModule():void {       
                                   var url:String = '';
                                   url += 'TestModule.swf';
                                   modInfo = ModuleManager.getModule(url);
                                   modInfo.addEventListener(ModuleEvent.ERROR,moduleReady);
                                   modInfo.addEventListener(ModuleEvent.READY,moduleReady);
                                   modInfo.load(null, null, null, moduleFactory);
                               }
                               public function moduleReady(event:ModuleEvent):void {               
                                   if (event.type == ModuleEvent.ERROR) {
                                       trace(event.errorText);
                                   }
                                   if (event.type == ModuleEvent.READY) {
                                       mod = modInfo.factory.create() as TestInterface;
                                       var el:IVisualElement = modInfo.factory.create() as IVisualElement;
                                       this.addElement(el);                   
                                   }
                               }
                               public function changeLabel(event:MouseEvent):void {
                                   mod.setLabel(inputLabel.text);
                               }
                               private function applyModuleSettings(e:Event):void {
                                   //mod = modL.child as TestInterface;                 
                               }
                           ]]>
                       </fx:Script>
                       <fx:Declarations>
                           <!-- Place non-visual elements (e.g., services, value objects) here -->
                       </fx:Declarations>
                       <s:layout>
                           <s:VerticalLayout/>
                       </s:layout>
                       <s:TextInput id="inputLabel"/>
                       <s:Button label="Apply" click="changeLabel(event)"/>
                       <!--<mx:ModuleLoader id="modL" width="100%" url="TestModule.swf" ready="applyModuleSettings(event)"
                           />-->
                  </s:Application>

                   

                  This is module manager version.

                   

                  Commenting the "loadTestModule();" in onCreate function, and uncommenting the 'modL' (module loader) part of the code will make it the ModuleLoader version.

                   

                   

                  Actually in the module manager version, the label is not getting changed in the module, when the interface function is called. Which makes me to think I am missing something, but everything looks fine.

                   

                  The SDK version I am using is 4.1.0.16076

                  • 7. Re: Is it possible to call module component's function through interface function
                    FM_Flame Level 1

                    Hi, yes I figured out your problem now when i have your code.

                     

                    See this here:

                     

                    mod = modInfo.factory.create() as TestInterface;
                    var el:IVisualElement = modInfo.factory.create() as IVisualElement;
                    this.addElement(el);            

                     

                    This is wrong - you create 2 separate instances of the module, one of which you create - "el", and the other one not - "mod".

                     

                    This should look like this:

                     

                    var el:IVisualElement = modInfo.factory.create() as IVisualElement;
                    // Note: usually I use var el:Module = modInfo.factory.create() as Module; Didn't need at least for now to cast it like IVisualElement but I know it's not wrong, I've read in some articles time before If i can recall correct that it does give you access to some methods, but not sure.

                    mod = el as TestInterface;

                    addElement(el);

                     

                    First you create the instance of the module with factory.create(), then you cast it to the interface.

                     

                    F

                    • 8. Re: Is it possible to call module component's function through interface function
                      guns3218 Level 1

                      Thanks a lot. That solves and explains the issue.Now I clearly understand why I was not able to access the component, and also why the parentDocument was null. The created element and module interface are two separate instances, because they are created separately using separate factory.create(). I never thought this would be the problem. Took lot of time to debug this. Thanks for your patience and response.