Search code examples
apache-flexcommunicationmodulecontextmenuviewstack

flex 3 passing data from modules to parent application to switch views in the viewstack


Hello Fellow stackoverflowers,

I´m stuck writing a piece of code. I have application with a viewstack witch load 5 modules. each module is loaded via the moduleLoader tag and they all have an id.

Every loaded module has a context menu. the context menu has 5 menuItems. one menuItem for each view for the viewstack.

The context menu is loaded via xml.

this is my application file.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
      layout="absolute"
      backgroundColor="#b1b1b1"
      backgroundGradientColors="[#b1b1b1,#252525]">

<mx:Script>
<![CDATA[
import mx.core.Container;


        //change viewstack views via modules context menu
        public function switchView(viewId:String):void
     {
         var container:Container = Container(tops.getChildByName(viewId));
         if (container != null)
         {
             tops.selectedChild = container;
         }
     }
]]>
</mx:Script>

<mx:ViewStack id="tops" width="100%" height="100%">
  <mx:ModuleLoader id="admin" url="view/admin.swf" width="100%" height="100%"/>
  <mx:ModuleLoader id="tv" url="view/tv.swf" width="100%" height="100%"/>
  <mx:ModuleLoader id="community" url="view/community.swf" width="100%" height="100%"/>
  <mx:ModuleLoader id="shop" url="view/shop.swf" width="100%" height="100%"/>
  <mx:ModuleLoader id="communicator" url="view/communicator.swf" width="100%" height="100%"/>
</mx:ViewStack>


</mx:Application>

and this is my switch statement in my Module

public function changeView():void{
switch(action) {
case "admin":
    parentApplication.switchView("admin");
break;
case "tv":
    parentApplication.switchView("tv");
break;
case "shop":
    parentApplication.switchView("shop");
break;
case "community":
    parentApplication.switchView("community");
break;
case "default":
    parentApplication.switchView("communicator");
break;
 }
}

and this is my context menu xml

  <mx:XML id="appMenu">
    <root>
        <menuitem enabled="false"/>
        <menuitem label="Administration" action="admin" icon="adminMDI"/>
        <menuitem label="Television" action="tv" icon="tvMDI"/>
        <menuitem label="Community" action="community" icon="communityMDI"/>
        <menuitem label="Shopping Mall" action="shop" icon="shoppingMallMDI"/>
        <menuitem label="Communicator" action="default" icon="communicatorMDI"/>                                                              
    </root>
  </mx:XML>

What i would like to do is switch the views in the viewstack by clicking on one of the menuitems in the context menu. i can't communicate from my module to the application. What am i doing wrong? what must i do? Can anybody help me out?

Oyeah before i forget

the xml of the context menu is in the module but, the context menu is in a as file that extensiate a button.

please can any body give me a good example how to accomplish this.

Thank

DJ


Solution

  • I see a couple issues before getting into the multi-module communication.

    First, in your changeView() function, you are declaring the variable action and then switching on it.

    public function changeView():void {
        var action:String;
        switch(action) {
            // action will always be null here.
        }
    }
    

    Because you don't have a 'default' case in your switch statement(s), parentApplication.switchView will never be called.

    Also, for the sake of brevity, you can write switch statements like this:

    switch(action) {
        case "admin":
            parentApplication.changeView("admin");
        break;
        case "tv":
            parentApplication.changeView("tv");
        break;
        case "shop":
            parentApplication.changeView("shop");
        break;
        // ... etc ...
        default:
            // this gets called if action doesn't match anything.
        break;
    }
    

    Finally, you could save yourself even more typing because your action and module ids are the same, you could do this:

    public function changeView(action:String):void {
        parentApplication.changeView(action);
    }
    

    Maybe try those things and then updating your question (also, the XML for your context menus didn't render correctly in your question). That may help the community solve your issue a little easier.

    UPDATE

    I don't think the problem is in the module communication. I built a simple project that does what I think you're looking for. I've posted the source below.

    mmodules.mxml

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" implements="interfaces.IApplication">
        <mx:Script>
            <![CDATA[
                import mx.core.Container;
                public function changeView(action:String):void {
                    viewstack.selectedChild = viewstack.getChildByName(action) as Container;
                }
            ]]>
        </mx:Script>
        <mx:ViewStack id="viewstack" width="100%" height="100%">
            <mx:ModuleLoader id="module1" url="views/module1.swf" />
            <mx:ModuleLoader id="module2" url="views/module2.swf" />
        </mx:ViewStack>
    </mx:Application>
    

    interfaces/IApplication.as

    package interfaces {
        public interface IApplication {
            function changeView(action:String);
        }
    }
    

    views/module1.mxml

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
        <mx:Script>
            <![CDATA[
                import interfaces.IApplication;
                import mx.events.MenuEvent;
                import mx.controls.Menu;
                /**
                * Dynamically builds a menu.
                */
                protected function showMenu():void {
                    var m:Menu = Menu.createMenu(null, menuData, false);
                    m.labelField = '@label';
                    m.addEventListener(MenuEvent.ITEM_CLICK, onItemClick);
                    m.show(10, 10);
                }
                /**
                * Handles whenever an item in the menu is clicked.
                */
                protected function onItemClick(e:MenuEvent):void {
                    if(e && e.item && e.item is XML) {
                        changeView(e.item.@action);
                    }
                }
                /**
                * Tells the parent application to switch views.
                */
                protected function changeView(action:String):void {
                    var app:IApplication = parentApplication as IApplication;
                    switch(action) {
                        case 'module1':
                            app.changeView('module1');
                        break;
                        case 'module2':
                            app.changeView('module2');
                        break;
                    }
                }
            ]]>
        </mx:Script>
        <mx:XML format="e4x" id="menuData">
            <root>
                <menuitem label="Module 1" action="module1" />
                <menuitem label="Module 2" action="module2" />
            </root>
        </mx:XML>
        <mx:Button label="Show menu" click="showMenu()" />
    </mx:Module>
    

    Hope that helps.