5 Replies Latest reply on Mar 18, 2010 4:47 PM by smon_ed

    Adding children to NavigatorContent dynamically using Actionscript

    smon_ed Level 1
      <ViewStack x="10" y="143" id="screens" width="731" height="514">
       <s:NavigatorContent name="splashScreen" label="splashScreen" width="100%" height="100%">
        <s:Label text="Splash Screen"/>
       </s:NavigatorContent>
        
       <s:NavigatorContent name="levelsMenu" label="levelsMenu" width="100%" height="100%">
        <s:Label text="Levels Menu"/>
       </s:NavigatorContent>
        
       <s:NavigatorContent name="unitsMenu" label="unitsMenu" width="100%" height="100%">
        <s:Group id="myGroup">
         <s:Label text="Units Menu"/>
        </s:Group>
        <s:Button id="my_btn" label="My Button" x="0" y="100" width="90" baseColor="#E65B00" cornerRadius="0"/>
       </s:NavigatorContent>
        
      </mx:ViewStack>
      

       

      Can someone please tell me how I might be able to add an element to the NavigatorContent "unitsMenu"?

       

      I have an AS class that is passed the NavigatorContent and the reference is the public var _target and so my actionscript reads:

       

      var curButton:Button = new Button();
      curButton.id = "myOtherButton";
      curButton.label = "My Other Button";
      _target.addElement(curButton);
      

       

      When I trace _target I get the result:

       

      _target = main0.WindowedApplicationSkin2.Group3.contentGroup.screens.unitsMenu

       

      Which is what I expected.

       

      And now I'm having difficulty adding elements to this NavigatorContent dynamically and I want to access these repeatedly for all sorts of dynamic operations.  How do I do this?

        • 1. Re: Adding children to NavigatorContent dynamically using Actionscript
          Flex harUI Adobe Employee

          Use id="" not name="".  Then you can access unitsMenu.

          1 person found this helpful
          • 2. Re: Adding children to NavigatorContent dynamically using Actionscript
            smon_ed Level 1

            EDIT:

             

             

            ok - I've simplified things a bit by doing away with my Main as class and the class I am attempting to add a button from.  So now I have it all in a single mxml file like so:

             

            <?xml version="1.0" encoding="utf-8"?>
            <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                    xmlns:s="library://ns.adobe.com/flex/spark" 
                    xmlns:mx="library://ns.adobe.com/flex/halo" 
                    xmlns:local="*"
                    applicationComplete="appStartup()" 
                    width="980" height="750"
                    showStatusBar="false">
             
             <fx:Script>
              <![CDATA[   
               import spark.components.Button;
               
               public function appStartup():void
               {
                //set the screen to units menu:
                screens.selectedIndex = 1;
                
                //add a button to units menu:
                var unitButton:Button = new Button();
                unitButton.label = "unit 1";
                unitButton.y = 100;
                
                //add this button to unitsMenu
                //HOW??
                
               }
              ]]>
             </fx:Script>
             
             <mx:ViewStack x="10" y="143" id="screens" width="731" height="514">
              <s:NavigatorContent id="splashScreen" label="splashScreen" width="100%" height="100%">
               <s:Label text="Splash Screen"/>
              </s:NavigatorContent>
              
              <s:NavigatorContent id="unitsMenu" label="unitsMenu" width="100%" height="100%">
               <s:Label text="Units Menu"/>
              </s:NavigatorContent>
              
              <s:NavigatorContent id="t01" label="t01" width="100%" height="100%" x="233">
               <s:Label text="screen t01"/>
              </s:NavigatorContent>
              
             </mx:ViewStack>
             
             
             
             
             <fx:Declarations>
              <!-- Place non-visual elements (e.g., services, value objects) here -->
             </fx:Declarations>
            </s:WindowedApplication>
            


            Can anyone show me how to add children into the unitsMenu NavigatorContent inside the ViewStack?  And change the label.text for the existing label for example?

             

            I'm sure it's simple but I just am really stuck with it.

             

            Thanks in advance.

            • 3. Re: Adding children to NavigatorContent dynamically using Actionscript
              kubens

              <?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"
                             xmlns:mx="library://ns.adobe.com/flex/halo"
                             minWidth="1024"
                             minHeight="768"
              >
                  <fx:Declarations>
                      <!-- Place non-visual elements (e.g., services, value objects) here -->
                  </fx:Declarations>
                 
                 
                  <fx:Script>
                      <![CDATA[
                          import mx.controls.Alert;
                          import mx.core.FlexGlobals;
                 
                          public var btnCounter:int = 0;
                          protected function my_btn_clickHandler(event:MouseEvent):void
                          {
                              var btn:Button = new Button();
                              btn.id = "my_other_btn"+btnCounter;
                              btn.x = 100;
                              btn.y = btnCounter*20;
                              btn.label = "My Other Button "+btnCounter;
                             
                              FlexGlobals.topLevelApplication['unitsMenu'].addElement(btn);
                              FlexGlobals.topLevelApplication['myGroupLabel'].text = 'Units Menu' + btnCounter
                                 
                              btnCounter++;
                          }

               

                      ]]>
                  </fx:Script>
                                 
                      <s:NavigatorContent id="unitsMenu" label="unitsMenu" width="100%" height="100%">
                          <s:Group id="myGroup">
                              <s:Label id="myGroupLabel" text="Units Menu"/>
                          </s:Group>
                          <s:Button id="my_btn" click="my_btn_clickHandler(event)" label="My Button" x="0" y="100" width="90" cornerRadius="0"/>
                      </s:NavigatorContent>
                 
              </s:Application>

               

              Tested with SDK 4.1.0.14590

              Hope that helps

               

              Best regards

              Wolfgang

              • 4. Re: Adding children to NavigatorContent dynamically using Actionscript
                smon_ed Level 1

                Thanks Wolfgang - it's not really the correct situation - my issue is that I am unable to populate a NavigationContent object within a ViewStack, as I outlined in my code above.

                 

                The issue is that when I attempt to addElement(button) to the NavigatorContent object "unitsMenu" within a ViewStack, the button does not display.

                 

                For example - this does not work:

                 

                <?xml version="1.0" encoding="utf-8"?>
                <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                        xmlns:s="library://ns.adobe.com/flex/spark" 
                        xmlns:mx="library://ns.adobe.com/flex/halo" 
                        xmlns:local="*"
                        applicationComplete="appStartup()" 
                        width="980" height="750"
                        showStatusBar="false">
                 
                 
                 <fx:Script>
                  <![CDATA[   
                   import spark.components.Button;
                   
                   public function appStartup():void
                   {
                    //set the viewStack to display unitsMenu:
                    screens.selectedIndex = 1;
                    
                    trace(screens.getChildByName("unitsMenu"));
                    //returns:
                    //main0.WindowedApplicationSkin2.Group3.contentGroup.screens.unitsMenu
                    
                    var btn:Button = new Button();
                    btn.id = "myButton";
                    btn.label="foo";
                    
                    //screens.getChildByName("unitsMenu").addElement(btn);
                    //this causes an issue:
                    //problem 1061: Call to a possibly undefined method addElement through a reference with static type flash.display:DisplayObject.
                    
                    //ok then, so I'll try it this way:
                    var targetContainer:Object = screens.getChildByName("unitsMenu");
                    trace(targetContainer);
                    //returns:
                    //main0.WindowedApplicationSkin2.Group3.contentGroup.screens.unitsMenu
                    
                    targetContainer.addElement(btn);
                    
                    //doesn't throw any errors but the button does not appear
                    //but check this out:
                    
                    trace(targetContainer.skin.contentGroup.getChildAt(0));
                    //returns:
                    //main0.WindowedApplicationSkin2.Group3.contentGroup.screens.unitsMenu.SkinnableContainerSkin12.contentGroup.myButton
                    
                    //   I AM CONFUSED !!!
                    
                    
                   }
                  ]]>
                 </fx:Script>
                 
                 <mx:ViewStack x="10" y="143" id="screens" width="731" height="514">
                  <s:NavigatorContent id="splashScreen" label="splashScreen" width="100%" height="100%">
                   <s:Label text="Splash Screen"/>
                  </s:NavigatorContent>
                  
                  <s:NavigatorContent id="unitsMenu" label="unitsMenu" width="100%" height="100%">
                   <s:Label text="Units Menu"/>
                  </s:NavigatorContent>
                  
                  <s:NavigatorContent id="t01" label="t01" width="100%" height="100%" x="233">
                   <s:Label text="screen t01"/>
                  </s:NavigatorContent>
                  
                 </mx:ViewStack>
                 
                 
                 
                 
                 <fx:Declarations>
                  <!-- Place non-visual elements (e.g., services, value objects) here -->
                 </fx:Declarations>
                </s:WindowedApplication>
                
                • 5. Re: Adding children to NavigatorContent dynamically using Actionscript
                  smon_ed Level 1

                  Setting the creationPolicy of my viewStack to creationPolicy="all" allowed the new button to be drawn.

                   

                  I also have seen this, which is quite relevant to some issues accessing the existing components:

                   

                  http://opensource.adobe.com/wiki/display/flexsdk/Gumbo+DOM+Tree+API

                   

                  Specifically this quote:

                   

                           ...even though it looks like Panel's children should be a button, a label, and a checkbox; it's only real child is a panel skin instance. And the button, label, and checkbox get pushed down to become children of the contentGroup in the skin file. There are a few ways to access the Button in the panel: myPanel.getElementAt(0) or myPanel.contentGroup.getElementAt(0) or myPanel.skin.contentGroup.getElementAt(0).

                   

                  All SkinnableComponent's have a skin property. In an SkinnableContainer, the children of the components are actually pushed down to the skin's contentGroup. The component tree refers to the semantic tree translated from MXML. In the Panel example, this would just include, the Panel and its children: a button, a label, and a checkbox. The layout tree refers to the actual tree seen by the layout system, the layout tree due to skinning. In the Panel example, this would include the panel, the panel skin, all the panel skin's children, and all the panel's children that are actually pushed down into the contentGroup of the panel skin.

                   

                  The layout tree doesn't necessarily correlate to the display list tree that Flash sees. This is because GraphicElements are not innately display objects. Because of performance reasons, they implement display object sharing to minimize the number of display objects.

                   

                  IVisualElementContainer is the interface that defines the content APIs. In Spark, Skin, Group, and SkinnableContainer are the components for holding visual elements and implement this interface. To provide consistency, MX's Container will also implement this interface and just be a facade for addChild(), numChildren, etc...

                   

                  So this explains why I am not able to access the child components as I expected... they are being pushed down into the container's skin contentGroup.... oh yeah.... that was obvious then.... erm......

                   

                  I think that needs to be put in the main Flex 4 documentation with some example AS snippets, if possible.  It's just taken me all day to find this.