2 Replies Latest reply on Sep 4, 2010 5:49 PM by Shongrunden

    Unable to access an object after creating it

    JoeRocket1148

      Hi,

       

      I have had a problem with twice now and would really appreciate if someone can explain this. I made a real simple example to show what I am having problems with.

       

      I have a custom component.

      I have a button in the main application that on click, changes some trivial text in the custom component.

      I remove the component from its parent.

      I create and add a new instance of the component to the same parent element and with the same id.

      I click the button to change the text in the component with the same function that worked before, but Flex can't find the new instance of the component.

       

      Main.mxml

      <?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/mx" minWidth="955" minHeight="600" xmlns:local="*">
      
           <fx:Script>
                <![CDATA[
                     protected function button1_clickHandler(event:MouseEvent):void
                     {
                          trace(comp.text1.text);
                          comp.text1.text = "text changed in the comp";
                     }
      
                     protected function button2_clickHandler(event:MouseEvent):void
                     {
                          vgroup1.removeElement(comp);
                     }
      
      
                     protected function button3_clickHandler(event:MouseEvent):void
                     {
                          var newComp:comp1 = new comp1();
                          trace("Why does this work? I thought children are not created for this object until addElement. "+ newComp.text1.text);
                          vgroup1.addElement(newComp);
                          newComp.id = "comp";
                     }
      
                ]]>
           </fx:Script>
      
           <s:VGroup top="50" left="15">
                <s:VGroup id="vgroup1">
                     <s:RichText text="This text exists in teh main app." />
                     <local:comp1 id="comp" />
                </s:VGroup>
                <s:Button label="Change comp text" click="button1_clickHandler(event)" />
                <s:Button label="Delete comp" click="button2_clickHandler(event)" />
                <s:Button label="Add comp" click="button3_clickHandler(event)" />
           </s:VGroup>
      </s:Application>
      

       

      The custom component is just a component with one RichText. Here is the output from the trace:

       

      This text exists in comp1.
      Why does this work? I thought children are not created for this object until addElement. This text exists in comp1.
      text changed in the comp
      ArgumentError: comp is not found in this Group.
          at spark.components::Group/getElementIndex()

       


      Two questions:

       

      1. Why does the function call fail the second time?

      2. Why is the text box accessable right after instantiation? I thought that in the component lifecycle, children elements are created after the addElement() call.

       

      Thanks in advance for the help - this would really help my Flex education.

        • 1. Re: Unable to access an object after creating it
          Subeesh Arakkan Level 4

          If I understood this correctly, the "id" in flex is not a property of a class. When a component is declared in MXML, this value becomes the instance name of the object. So it doesnt make a difference to the component when you set it in actionscript.

           

          In your application, you can use the removeElementAt() and getElementAt() methods for removing and updating the component.

           

          comp(vgroup1.getElementAt(1)).text1.text = "text changed in the comp";
          

           

          vgroup1.removeElementAt(1);
          
          • 2. Re: Unable to access an object after creating it
            Shongrunden Adobe Employee

            Regarding #2:  I'm not sure I fully understand your question but believe you are asking about deferred instantiation.  If your custom component extends from Group then it doesn't support deferred instantiation and all the children will be created when the Group is instantiated.  If you had extended SkinnableContainer then you wouldn't be able to access the children until it was added to the DisplayList using addElement() or you called createDeferredContent().

             

            Here's a code example that demonstrates the difference:

             

            <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                           xmlns:s="library://ns.adobe.com/flex/spark"
                           creationComplete="init()">
               
                <fx:Declarations>
                    <fx:Component className="CustomGroup">
                        <s:Group>
                            <s:Button id="inner" label="inner" />
                        </s:Group>
                    </fx:Component>
                    <fx:Component className="CustomSkinnableContainer">
                        <s:SkinnableContainer>
                            <s:Button id="inner" label="inner" />
                        </s:SkinnableContainer>
                    </fx:Component>
                </fx:Declarations>
               
                <fx:Script>
                    <![CDATA[
                        private function init():void {
                            // this works fine even though its not on the DisplayList
                            var newGroup:CustomGroup = new CustomGroup();
                            newGroup.inner.label = "works fine";
                           
                            // this inner child isn't created yet since its not on the DisplayList and
                            // SkinnableContainer supports deferred instantiation
                            var newSC:CustomSkinnableContainer = new CustomSkinnableContainer();
                            newSC.inner.label = "causes RTE";
                           
                            // this works fine because we call createDeferredContent() before accessing the
                            // inner child
                            var newSC2:CustomSkinnableContainer = new CustomSkinnableContainer();
                            newSC2.createDeferredContent();
                            newSC2.inner.label = "works fine";
                           
                        }
                    ]]>
                </fx:Script>
            </s:Application>