8 Replies Latest reply on Jun 30, 2011 3:19 AM by Rui Silva

    flash builder 4.5  application.application.getchildbyname

    Starlover_jacob Level 1

      Hi,

       

      I came from flex 3 to the newer version flash builder 4.5, so not everything is clear for me..

      for example:

      I have a project and i dynamically add a custom component on it like this:

       

       var mycanvas:MainCanvas=null;
           mycanvas = new MainCanvas();
           mycanvas.name = "myMainCanvas";
           this.addchild(mycanvas);

       

      i noticed that in the new spark settings addchild no longer is used, so this.addchild would be this.addelement.

      fine, by me.. now my problem

      later in my program I want to refer to that element.

      in flex3 i did:

       

      //maincanvas is my custom component (a canvas with stuff in it like a viewstack)
      var myMainCanvas:MainCanvas=null;
      myMainCanvas = MainCanvas(Application.application.getChildByName("myMainCanvas");
      

       

      i now do:

      myMainCanvas = MainCanvas(FlexGlobals.topLevelApplication.getChildByName("myMainCanvas"));
      

      this because application.application is no longer supported... also fine by me..

       

      the problem: when i run this.. the program gives an error that myMainCanvas is of a null object reference.

      What am i doing wrong here?

      The custom component (canvas) i added to the main application is showing on my screen.. so it is definitely loaded..

       

      please some help

        • 1. Re: flash builder 4.5  application.application.getchildbyname
          pauland Level 4

          I have a feeling that the "this" here:

          this.addchild(mycanvas);

           

          isn't actually the application.

          • 2. Re: flash builder 4.5  application.application.getchildbyname
            Starlover_jacob Level 1

            well... when i make a variable of toplevelapplication and i watch that var:

            var test:Object=FlexGlobals.topLevelApplication;

             

            I see that mycanvas ended up inside:

            ContentGroup - _mxmlContent - [0] - name = mycanvas

             

            So i think all elements added at application level are placed inside the contentgroup.

            The thing now is, how do i get to it?

             

            Well this is the way to get to it:

            it needed contentGroup.

             

             var currentPage:MainCanvas=null;
            currentPage = MainCanvas(FlexGlobals.topLevelApplication.contentGroup.getChildByName("myMainCanvas"));            
                            
            

             

            When you didn't add a component using this.addelement(), but implemented a component by using mxml tags, you can refer to it like this:

            //example of a custom component called menu.

             

            <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"
            xmlns:generalmenu="menufolder.menu.*">
                <fx:Script>
                    <![CDATA[
                      import general.menu.menu;
                      import mx.core.FlexGlobals;
            
                     public function calltomenu()
                      {
                           var mymenu:menu=menu(FlexGlobals.topLevelApplication.mymenu);
                      }
                    ]]>
                </fx:Script>
            
            <generalmenu:menu x="59" y="58" id="mymenu"/>
            </s:Application>
            

             

             

            Greets, J.

            • 4. Re: flash builder 4.5  application.application.getchildbyname
              Rui Silva Level 3

              Hi Jacob,

               

              Just some quick notes about your resolution:

               

              1. Regarding the retrieval of a dinamically created element at the application level, while it is true that you can reach using the method you suggest, it would be far more efficient to hold somewhere a reference to the element and use that reference instead. The fact is that getChildByName is not a very efficient method and depending on the logic of your application might imply an unwanted performance hit. Also, holding a string representing the element's in memory for future reference occupies more memory than an object reference. You might use an external class (static or singleton) to hold all your element references, or you can use an application level property to do the same. It all depends on the complexity of your application;

               

              2. Regarding the reference to MXML declared elements, you don't need to to reference them using FlexGlobals.topLevelApplication, at least when you're coding in the application level. If you have to reference it from outside of the application class, then this would be needed, but still a better approach would be to pass the reference to the code that needs it instead of having it reach topLevelApplication to get it.

               

              Cheers,

              Rui Silva

              • 5. Re: flash builder 4.5  application.application.getchildbyname
                Starlover_jacob Level 1

                Hi rui silva,

                 

                thanx for your answer, i'm always in for performance improvements.

                Regarding to your first answer, can you give me a tutorial on this? I am one of those programmers that just starts with the project, and when a method works.. well i keep to it.. (just to save time and not spend it on searching for better options.) This will result to options that are not always the best..

                 

                Any tips on how to learn yourselve flex/flash builder 4/programming the right way?

                 

                Greets, Jacob

                • 6. Re: flash builder 4.5  application.application.getchildbyname
                  Rui Silva Level 3

                  Suppose you have a class like the following:

                   

                  package {
                       public class AppModel {
                            public var myCanvas:MainCanvas;
                       }
                  }
                  

                   

                  Then on your code you could create a instance of that class and set the myCanvas property with the newly created MainCanvas class:

                   

                  var model:AppModel = new AppModel();
                  model.myCanvas = new MainCanvas();
                  

                   

                  From that point on, whenever you need to reference that instance of MainCanvas, you just reference it through the model:

                   

                  model.myCanvas.width = 100;
                  

                   

                  If you have to use the myCanvas throughout several classes in the application, it would be better to make it a static property and reference it directly through the class reference. So:

                   

                  package {
                       public class AppModel {
                            public static var myCanvas:MainCanvas;
                       }
                  }
                  

                   

                  Then:

                   

                  AppModel.myCanvas = new MainCanvas();
                  

                   

                  And finally, whenever you need to reference it:

                   

                  AppModel.mycanvas.width = 100;
                  

                   

                  Hope this helps. If it does, please signal the thread as answered.

                   

                  Cheers,

                  Rui

                  • 7. Re: flash builder 4.5  application.application.getchildbyname
                    Starlover_jacob Level 1

                    when you are Building Flex and Adobe Air applications from the same code base (Unified Modeling Language)


                    var currentPage:MainCanvas=null;
                    currentPage = MainCanvas(FlexGlobals.topLevelApplication.contentGroup.getChildByName("myMainCanvas")); 
                    


                    will not work in the general project because the flex part that runs on the web does not know contentGroup.

                    you can only use it inside the air part of your project.

                     


                    So.... the suggestions from rui silva above are the best solution.

                     

                     

                    question to rui silva;

                    Do you agree that using it like i did in my previous post

                    ( see the part: using mxml tags, you can refer to it like this: //example of a custom component called menu.)

                    would be a correct solution ?

                    Or would it still be better to create a central package where you create public vars of all components you use inside your application and refer to it the way you explained? so you do not use flexglobals.toplevelapplication.customcomponentname.

                     

                    greets, jacob

                    • 8. Re: flash builder 4.5  application.application.getchildbyname
                      Rui Silva Level 3

                      Hi Jacob,

                       

                      Sorry if I'm repeating myself, but please signal the thread as answered if you feel that your original question has been solved. People browsing the forums can see if a thread has been answered or not and opt to only go into the ones that are. Thanks.

                       

                      Regarding your question:

                       

                      In your concrete example, you wouldn't need to use the FlexGlobals.topLevelApplication.mymenu reference because MXML components are visible to all code in the application class. In fact, if you do so, you don't even have to cast it to its concrete type, because at that level its type is known, you could do this instead:

                       

                      <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"
                      xmlns:generalmenu="menufolder.menu.*">
                          <fx:Script>
                              <![CDATA[
                                import general.menu.menu;
                                import mx.core.FlexGlobals;
                      
                               public function calltomenu()
                                {
                                     var mymenu:menu = this.mymenu;
                                }
                              ]]>
                          </fx:Script>
                      
                      <generalmenu:menu x="59" y="58" id="mymenu"/>
                      </s:Application>

                       

                      This is perfectly correct and good practice. If you need to access mymenu from another class, then it would be best to use the reference stored in a static class property. There are other sollutions available and I would recommend you to check documentation on Design Patterns, Dependency Injection and Inversion of Control.

                       

                      In any case, if you don't want to go deeper into software development science, I'd recommmend you to look for alternatives whenever you have to reach to the topLeveApplication property. This is usually a simple and efficient code smell indicating that something could be done in a better way.

                       

                      Cheers,

                      Rui