Flex: Referencing component IDs within modules, nested viewstacks etc

1k Views Asked by At

The Adobe docs state:

The IDs for all tags in an MXML component, no matter how deeply nested they are, generate public variables of the component being defined. As a result, all id properties must be unique within a document. This also means that if you specified an ID for a component instance, you can access that component from anywhere in the application: from functions, external class files, imported ActionScript files, or inline scripts.

Which is fine if your application is all contained within one MXML, but I'm having trouble referencing IDs of components within Modules, and then inside ViewStacks/Navigation Containers within a given Module.

For instance,

If I can reference a module with FlexGlobals.topLevelApplication.myModule, shouldn't I be able to reference a Panel called myModulePanel with the following?

FlexGlobals.topLevelApplication.myModule.myModulePanel

or at least

FlexGlobals.topLevelApplication.myModule.getChildByName(myModulePanel)

for properties such as title, width etc?

Since component IDs are public variables (according to the docs), I didn't think I'd have to chain a series of .getChildByName() functions to drill down into component/container levels to access component properties, but the methods I've tried above don't seem to be working.

But if this is the case, do I really need to form a long chain of component references to access the children of ViewStacks etc then- and what is the best way to inspect this hierarchy?

Any suggestions would be greatly appreciated.

Thanks.

1

There are 1 best solutions below

0
On

You should create an interface for each module (or one main interface to which all your modules subscribe), defining methods that need to be called outside the modules. That way you interact with the interface, not the module itself, but the interface methods mediate between the module classes and the main application.

Using the IModuleInfo interface loaded by the ModuleManager should help you get to this. See this page for more info.

<?xml version="1.0"?>
<!-- modules/ModuleLoaderApp.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx"
    creationComplete="initApp()">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

    <fx:Script>
        <![CDATA[
        import mx.events.ModuleEvent;
        import mx.modules.ModuleManager;
        import mx.modules.IModuleInfo;        
        import mx.core.IVisualElement;

        public var info:IModuleInfo;

        private function initApp():void {
            info = ModuleManager.getModule("ColumnChartModule.swf");
            info.addEventListener(ModuleEvent.READY, modEventHandler);           

            /* Load the module into memory. Calling load() makes the
               IFlexModuleFactory available. You can then get an
               instance of the class using the factory's create()
               method. */
            info.load(null, null, null, moduleFactory);
        }

        /* Add an instance of the module's class to the display list. */        
        private function modEventHandler(e:ModuleEvent):void {
            /* For MX containers, cast to a DisplayObject. */
            vb1.addChild(info.factory.create() as DisplayObject);

            /* For Spark containers, cast to a UIComponent. */
            vg1.addElement(info.factory.create() as IVisualElement);
        }
        ]]>
    </fx:Script>

    <!-- MX container -->
    <mx:VBox id="vb1">
        <s:Label text="Module loaded in MX VBox container:"/>
    </mx:VBox>

    <!-- Spark container -->
    <s:VGroup id="vg1">
        <s:Label text="Module loaded in Spark VGroup container:"/>    
    </s:VGroup>

</s:Application>

Note that you can still create your own interfaces that give you control over the specific modules and their methods and properties. For example, I recently created an interface that returns a reference to two components (which are instances of Group but casts as UIComponent):

package main.flex.interfaces
{
    import flash.events.Event;
    import flash.events.IEventDispatcher;

    import mx.core.UIComponent;

    public interface IMyModuleName extends IEventDispatcher
    {
        function get mainGroup():UIComponent;

        function get buttonRow():UIComponent;

        function init(event:Event):void;

    }
}

In the modules themselves, then, accessing the mainGroup or buttonRow properties of the interface returns the named Group, such as

public function get mainGroup() : UIComponent {
  return someGroup;
}

...

<s:Group id="someGroup">
   <!-- content -->
</s:Group>

These are simplified and don't use the real IDs, but you should be able to get the idea from them.