8 Replies Latest reply on Apr 25, 2007 11:30 AM by artoix

    Create components at runtime

    artoix Level 1
      Hello,
      Application receives array of components names (such as "Button", "TextInput", "TextArea", etc) from web service and I need to create instances of these classes on the stage at runtime.
      What is the best practice for that?
      Thanks
        • 1. Re: Create components at runtime
          RianFowler
          I'd create an object generator that would parse the result from the web service using the parameters received as values for variables in dynamically generated controls.

          1. make a class for the container you are dynamically generating from the webservice
          2. create a private function that parses the result from the webservice into properties that will be used as parameters in the object generator functions
          3. create a public function that will return the dynamically generated container to the View that calls it
          3a: have this function call a creator for each of the objects it wants to contain
          3b: each of these object generators will use parameters parsed by the web service parsing function to create themselves
          3c: have this function organize the returned objects on itself
          3d: have this function return the container
          4. have the parent add the container
          • 2. Re: Create components at runtime
            artoix Level 1
            Thanks Rian,
            I've found this article by Keun Lee: http://www.cynergysystems.com/blogs/page/keunlee?entry=reflection_in_actionscript_3_0
            And that way works fine in my case.

            But I'm stuck on one error:
            when trying to create instance of the Form class I get an error:

            TypeError: Error #1034: Type Coercion failed: cannot convert mx.containers::Form$ to mx.core.UIComponent.

            Though Form is inherited from UIComponent.
            Does anyone know how to fix it?

            Here is a sample code:

            <?xml version="1.0" encoding="utf-8"?>
            <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="createForm();">
            <mx:Script>
            <![CDATA[
            import flash.utils.getDefinitionByName;
            import mx.core.UIComponent;
            import mx.containers.Form;

            private var fm:Form;
            private function createForm():void {
            var form:UIComponent = UIComponent( getDefinitionByName( "mx.containers.Form" ) as Class );
            this.addChild(form);
            }
            ]]>
            </mx:Script>
            </mx:Application>
            • 3. Create components at runtime
              RianFowler Level 1
              Thanks for the heads up on the article. I was actually looking to be able to do something similar today so this article will help me out.

              I ran your code and didn't get a coercion error. I'm not sure why you are getting it.
              • 4. Re: Create components at runtime
                artoix Level 1
                Rian,
                Works without error? Hm...
                How about this code:

                <?xml version="1.0" encoding="utf-8"?>
                <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="createForm();">
                <mx:Script>
                <![CDATA[
                import flash.utils.getDefinitionByName;
                import mx.core.UIComponent;
                import mx.containers.Form;
                import mx.containers.FormItem;
                import mx.controls.TextInput;

                private var fm:Form;
                private var fmi:FormItem;
                private var ti:TextInput;
                private function createForm():void {
                var form:UIComponent = UIComponent( getDefinitionByName( "mx.containers.Form" ) as Class );
                var formItem:UIComponent = UIComponent( getDefinitionByName( "mx.containers.FormItem" ) as Class );
                var textInput:UIComponent = UIComponent( getDefinitionByName( "mx.controls.TextInput" ) as Class );
                formItem.addChild(textInput);
                form.addChild(formItem);
                this.addChild(form);
                }
                ]]>
                </mx:Script>
                </mx:Application>

                This has to add TextInput component on the stage.
                But I still get an error:
                TypeError: Error #1034: Type Coercion failed: cannot convert mx.containers::Form$ to mx.core.UIComponent.

                Does anybody know what causes that error? (And actually is there error at all?)
                • 5. Re: Create components at runtime
                  RianFowler Level 1
                  Okay I figured out what I was doing wrong.

                  My knowledge is limited but it appears that the result from getDefinitionByName is returning a prototype of the respective objects. Whatever a prototype is, it cannot be explicitly converted into a DisplayObject or UIComponent to be displayed.

                  Let me know if you figure out how to do it. As for me, I'm going to make an object generator. It won't have the flexibility of what you're trying to do but it will get the job done.
                  • 6. Re: Create components at runtime
                    artoix Level 1
                    From Flex Help:
                    getDefinitionByName(name:String):Object
                    Method; Returns a reference to the class object of the class specified by the name parameter.

                    Sounds great! Works also!... but only with mx.controls.* package. When I try to convert any container to UIComponent a get a Coercion error. I tried to convert them to Container, to Sprite. But still get Coercion error, even though HBox, Form, FormItem are inherited from these classes.
                    I do not know what causes this error...
                    • 7. Re: Create components at runtime
                      artoix Level 1
                      The solution turned out to be quite easy:

                      import mx.containers.Form;
                      private var myForm:Form;

                      var FormClass:Class = getDefinitionByName("mx.containers.Form") as Class;
                      var form:Object = new FormClass();
                      activeTab.addChild( DisplayObject(form) );

                      It works fine! %)
                      Now I can generate interfaces dynamicaly, just by ckass names.
                      • 8. Re: Create components at runtime
                        artoix Level 1
                        ...in previous post activeTab is element from my code I forgot to replace...