1

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

DJ.
  • 2,031
  • 2
  • 13
  • 22
  • What kind of debugging have you already done? Have you checked that your function is firing at all with a simple trace or Alert.show()? If your function in the module is firing is it in turn firing the function in the parent app? I like to make a generic Alert.show('fired'); statement and move it down my function to make sure each part of it is firing. As soon as you move it past something that is causing an error it will fail. – invertedSpear Jan 11 '10 at 15:45

1 Answers1

5

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.

RJ Regenold
  • 1,748
  • 13
  • 17
  • thanks for the tips. I have edited the switch Statment. I have also thrown in a default. Unfornutatly i'm still stuck. Do you still have other tips i can chech out? – DJ. Jan 11 '10 at 10:02
  • Thank you for posting updates. The way you implemented the 'default' case in the switch isn't quite correct. I updated my code above to show how default should be used. Also, where is your 'action' variable coming from? If it's not too large, would you mind posting the code from one of your modules? – RJ Regenold Jan 11 '10 at 13:43
  • To post the code would not be so simple because i implement a lot of scripts. i can send you my project files by email. So that you can have a better look at it. – DJ. Jan 11 '10 at 16:54
  • actually i don't know where to put the action var - @action. I had it like this before public function changeView():void { var action:String; switch(action) { // } } – DJ. Jan 11 '10 at 16:57
  • I updated my answer to provide a small sample application that does what you're looking for. Let me know if you need any other help with it. – RJ Regenold Jan 11 '10 at 19:27
  • Thanks RJ, I works :))). I have another question, i would like to put the script in an interface, How must i alter the script to let it work (via Interface)? – DJ. Jan 12 '10 at 17:16
  • No problem. I updated my answer to show how you could have the main application class implement an interface, then use that interface in the modules. Is that what you're looking for? – RJ Regenold Jan 13 '10 at 01:49
  • @RJ Would it be a better approach to dispatch an event as opposed to creating an instance of the parent app and changing it's view? I'm thinking if the modules are truly reusable, then the module doesn't know what views are available at the parent. – adamcodes Feb 02 '10 at 15:31
  • You have given good example to me..i just saw your small application and did my work of the same task...i wanted to give credit of 50 to you..so i went to other answers of yours and increased the votes..:) – Pratap M Dec 19 '12 at 03:32
  • if possible could you check my another question..(Please)http://stackoverflow.com/questions/13935245/removing-the-child-componenent-when-a-button-is-clicked – Pratap M Dec 19 '12 at 03:34