20 Replies Latest reply on Jun 17, 2008 8:52 AM by SWiiT

    How to Create a Dynamic Form

    bitwyse Level 1
      Hi All,

      I am trying to build a dynamic form in Flex. The idea is to have a generic form component that contains a standard header and footer with a dynamically generated body. The body ( all the form items ) will be generated dynamically by an XML File. In theory to create any form all I would do is use the generic form and create the xml for the body and I'm done.

      I have been searching all over for a sample and have yet to find one. Has anyone done something like this? I see several similar questions in this forum but they have gone unanswered. I would greatly appreciate any help you can offer.

      Thanks

      STeveR
        • 1. Re: How to Create a Dynamic Form
          flexPro Level 1
          You could do this by creating a custom form component and overriding the commitProperties method, then adding a property to pass in the XML. I don't think it would be too hard. I also don't have the time to code up an example right now, but basically what you'd want to do is iterate through the XML (easy using E4X) and add a FormItem with the appropriate control as a child for each item in the XML within your commitProperties method (if and only if the xmlChildren property (or whatever) has changed). For example, if your XML was something like

          <form>
          <item type="TextInput" label="Name" />
          <item type="ComboBox" label="Country" values="['Canada','U.S.A.','Other']" />
          </form>

          then you'd want to add two FormItems as children with the labels given. You'd want to add a TextInput child to the first and a ComboBox child to the second. Sorry I don't have time to give a comprehensive example. Good luck!
          • 2. Re: How to Create a Dynamic Form
            bitwyse Level 1
            I'm working on a simple example similar to what you are saying. It is my assumption to use action script to generate the form items from the xml and then use addChild to add the form items. I am not quite sure how to implement it though. For example here is a simple form. . .

            <mx:Application borderStyle="solid" width="300" height="300"
            xmlns:mx=" http://www.adobe.com/2006/mxml">

            <mx:Model id="formDefinition" source="genericForm.xml"/>

            <mx:Form id="GenericForm">
            .....<local:formHeader/>
            // how do I get my form items to get built here by my action script?
            // I was going to use repeater but I've read that it's very slow . . .
            .....<local:formFooter/>
            </mx:Form>

            </mx:Application>
            • 3. Re: How to Create a Dynamic Form
              ntsiii Level 3
              Don't overlook mx:Repeater. It is much a simpler way to have data driven instantiation than using addChild.

              It should work fine with Form, though I never use Form, since it is too restrictive.

              Tracy
              • 4. Re: How to Create a Dynamic Form
                bitwyse Level 1
                Nancy, can you offer a bit of advice then on how or what would be the best practice to do what I'm trying to do?

                I've never used repeater before and have seen a limited example how it works. I'm not sure how to use it to create different form item types.
                • 5. Re: How to Create a Dynamic Form
                  ntsiii Level 3
                  Assuming you mean me, Tracy...

                  Are you creating a Form with formItems? Or different item displays based on data?

                  Repeater is slow compared to list-based controls only because it renders all the items, unless you tell it not to. With a reasonable number of items it is plenty fast. If you have a large number of items, don't let the Repeater scroll, but control the number of rows and then implement paged display instead of scrollbars.

                  Tracy
                  • 6. How to Create a Dynamic Form
                    bitwyse Level 1
                    I'm so sorry for the name confusion Tracy, color me embarrassed. A Nancy walked in my office as I was typing the message . . .
                    What I am trying to accomplish is to use one generic form component that can have a consistent header and footer with a dynamic body. For example, wouldn't it be nice to have the same code create an expense report as well as a time slip or an employee evaluation etc. . . .

                    All I would need to accomplish this would be different XML files to define the form items.

                    Does that make sense?

                    I'm not sure how to create the various tags for the different control types using the repeator for example,
                    <mx:FormItem label="Label">
                    ..........<mx:TextInput/>
                    </mx:FormItem>
                    <mx:FormItem label="Label">
                    <mx:ComboBox> . . . . . </mx:ComboBox>
                    </mx:FormItem>
                    <mx:RadioButtonGroup id="radiogroup1"/>
                    ......<mx:RadioButton label="Button 1" groupName="radiogroup1"/>
                    ......<mx:RadioButton label="Button 2" groupName="radiogroup1"/>
                    <mx:FormItem label="Label">

                    Or would I be doing this in Action Script?

                    I"m still fairly new to Flex and unsure how to implement this in the Flex environment. Any sample code to point me in the right direction would be VERY much appreciated.
                    • 7. Re: How to Create a Dynamic Form
                      ntsiii Level 3
                      Certainly, this is a very normal reqirement.

                      I don't have a sample handy, but what I would suggest is using a Viewstack as the base component for the repeater items:
                      <mx:Viewstack id="vsControls" .../>
                      <mx:Label text="{_xmlItemData.@value"} .../>
                      <mx:FormItem label="Label">
                      ..........<mx:TextInput/>
                      </mx:FormItem>
                      <mx:FormItem label="Label">
                      <mx:ComboBox> . . . . . </mx:ComboBox>
                      </mx:FormItem>
                      </mx:ViewStack>

                      then, in the set xmlItemData function, do a switch:
                      var sControlType:String = _xmlItemData.@controlType
                      switch (sControl) {
                      case "TextInput":
                      vsControls.selectedIndex = 1;
                      break;
                      ...

                      Use a custom component for the repeated item containing the above viewstack and call the repeater in your dynamicForm component like in the below example code:

                      Tracy

                      When working with Repeater, I advise creating a custom component that you will repeat, and pass it the entire "currentItem", In the component, implement a "setter" function to receive the currentItem data.

                      Now, in the component, you can code normally, binding to the data as you wish, without the hard to read currentItem references. You also avoid the binding warnings without the cast/conversion because the binding source is a true XML object.

                      And, you can dispatch events normally. In the event handler, you can reference the component via the event.target property, and thus get a direct reference to the dataProvider item. This is easier to write and read than having to use getRepeaterItem().

                      Here are some code snippets:

                      In the main app or component (note how "clean" and readable this is):
                      <mx:Application
                      <mx:VBox ...>
                      <mx:Repeater id="rp" dataProvider="{_xmlData}" ...>
                      <mycomp:MyRepeatedComponent xmlItem="{rp.currentItem}" .../>
                      </mx:Repeater
                      </mx:VBox>

                      And in the component, MyRepeatedComponent.mxml:
                      <?xml version="1.0" encoding="utf-8"?>
                      <mx:HBox ...
                      <mx:Script><![CDATA[
                      [Bindable]private var _xmlItem:XML;

                      public function set xmlData(xml:XML):void
                      {
                      _xmlItem = xml;
                      //do any special, non-bound ui stuff you want
                      }//
                      ]]></mx:Script>
                      <!-- Now declare the Item UI -->
                      <mx:Text id="lbDescription" text="{_xmlItem.@description}" width="100%" height="100%" />

                      • 8. Re: How to Create a Dynamic Form
                        ntsiii Level 3
                        You could use states instead of ViewStack, but they are more complicated.
                        • 9. Re: How to Create a Dynamic Form
                          bitwyse Level 1
                          I believe I understand what your reply said and have implemented it . . . well tried to anyhow LOL.
                          Needless to say it's not working. I'm a Flex Dork I guess.

                          Is there anyway you can look at the code and see where / what I'm doing
                          wrong?

                          Here is a link to the srcView http://xnet.psclistens.com/dynform/srcview/index.html since the
                          application won't run.

                          I appreciate all the time you are spending trying to help. You are amazing how much you help the community. I see your posts all over in various places. I hope one day to be able to give back as much as you do!!!!

                          You rock.

                          Thanks again,

                          STeveR
                          • 10. Re: How to Create a Dynamic Form
                            bitwyse Level 1
                            I was thinking about this the other day AGAIN, and I wondered, is it possible to do this using all actionscript?

                            For example, have an xml file that pretty much defined all the pieces and parts of a form. From HBox and VBox to text inputs and everything in between?

                            I haven't used action script to do that yet. One, is it possible? Two has anyone created a form completely in actionscript? Hhow would you implement that from a generic mxml component that would contain the header and footer with the dynamic body in the middle?

                            Anyone's thoughts on this would be greately appreciated.
                            • 11. Re: How to Create a Dynamic Form
                              bijayrungta
                              Using State the following program does work and have something similar to your requirements..
                              though not being generated according to an xml structure it does create form controls dynamically.

                              I myself am trying to create several form items from xml files and the content of the xml file I am not aware of completely.
                              It might have n number of occurances of a group of form controls all depending on the out put of the xml file which in itself ois generated dynamically from a server side script.

                              I have not really been successful in doing what I need. But I hope to solve this problem using the approach taken in this example. but I believe there must be a better way to do what I am trying to do. AM trying to figure this out since yesterday and yeah I am making progress and hope to resolve it soon...

                              I need to comeplete it today itself..

                              will get back with more that comes to my mind.

                              If anyone has any thoughts on it Please do post back..

                              -------------------------------------------------------------------------------------

                              <?xml version="1.0"?>
                              <!-- states\StatesDefInstan.mxml -->
                              <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml"
                              initialize="initializeApplication();">

                              <mx:Script>
                              <![CDATA[
                              import mx.core.*;
                              import mx.states.*;

                              private function initializeApplication():void {
                              //Code for adding a static button.
                              // Create the Button to be added
                              var newButton:Button = new Button();
                              newButton.label = "New Button";

                              // Create an AddChild object that adds the button.
                              var addChild:AddChild = new AddChild();
                              addChild.relativeTo = myPanel;
                              addChild.target = newButton;

                              // Create a State object
                              var newState:State = new State();
                              newState.name = "added";
                              newState.overrides = new Array();
                              newState.overrides.push(addChild);

                              // Initialize the states property of the Application.
                              // and add the new state.
                              states = new Array ();
                              states.push(newState);

                              //Code for adding a dynamically created button.
                              // Create an add AddChild object that adds the button.
                              var addChildDyn:AddChild = new AddChild();
                              addChildDyn.relativeTo = myPanel;

                              // Explicitly set the AddChild targetFactory property
                              // to a factory
                              // that runs the createMyButton method to create the button.
                              addChildDyn.targetFactory =
                              new DeferredInstanceFromFunction(createMyButton);

                              // Create State object with the addChildDyn override.
                              var newState2:State = new State();
                              newState2.name = "dynAdded";
                              newState2.overrides = new Array();
                              newState2.overrides.push(addChildDyn);

                              //Add the state to the Application's states property.
                              states.push(newState2);
                              }

                              // Function to create a new Button control.
                              public function createMyButton():Object {
                              var newButton:Button = new Button();
                              newButton.label = "New Dynamic Button";
                              return newButton;
                              }

                              ]]>
                              </mx:Script>
                              <mx:Panel id="myPanel"
                              title="Static and dynamic states"
                              width="300" height="150">
                              <!-- If the current state is not the added state, change to the
                              added state; if the current state is the added state,
                              change to the base state. -->
                              <mx:Button id="myButton" label="Toggle Static Button"
                              click="currentState = currentState == 'added' ? '' : 'added';"/>
                              <!-- If the current state is not the dynAdded state, change to the
                              dynAdded state; if current state is the dynAdded state,
                              change to the base state. -->
                              <mx:Button id="myButton2"
                              label="Toggle Dynamic Button"
                              click="currentState =
                              currentState == 'dynAdded' ? '' : 'dynAdded';"/>
                              </mx:Panel>
                              </mx:Application>

                              ------------------------------------------------------------------------------------------ -------------


                              Thanks,
                              Bijay
                              • 13. Re: How to Create a Dynamic Form
                                bitwyse Level 1
                                Here is my first pass at a somewhat dynamic form.
                                http://xnet.psclistens.com/psc/dynaform/dynamicform.html

                                I published the source. It's obviously not done and needs some work still but I think it's going to be a good foundation for me at least to create all my forms by creating different xml input files.

                                I have a couple of issues to address still and would love some feedback from more experienced Flex developers out there if possible . . .

                                1. When I create a form dynamically as you can see it doesn't line up correctly like a regular <mx:form> . . .. Any ideas how to fix that?

                                2. I need to create a lookup routine to populate default field values, combo box choices etc. . .

                                3. I need a generic form of submit to iterate over all the form items for validation ( which will end up as an attributte in the xml file ). Looking for some generic validation routines if anyone has something they want to share????

                                Thanks for any feedback you can provide . . .
                                • 14. Re: How to Create a Dynamic Form
                                  bijayrungta Level 1
                                  I too was able to achieve this.

                                  Here is a page where I am creating the entire page dynamically..
                                  http://aurosyssolutions.com/flexgui/_dev-2007-09-08_04-30/bin/AssessmentProgram.html

                                  am in a hurry, Will post in detail soon.

                                  it was pretty straight forward. Simply addChild function worked for all GUIObjects.

                                  You can actually manipulate everything in Flecx through ActionScript just as you can manipulate your HTML Document in javascript.

                                  Thanks,
                                  Bijay
                                  • 15. Re: How to Create a Dynamic Form
                                    bitwyse Level 1
                                    Hi Bijay,

                                    I would love to see your source code cuz I see your form is nicely lined up and mine is a mess. :(

                                    Thanks in advance for your help!
                                    • 16. Re: How to Create a Dynamic Form
                                      bijayrungta Level 1
                                      Download the required files from the location http://bijay.rungta.googlepages.com/_dev-2007-09-08_04-30.rar

                                      Here I had displayed the form controls at the Top statically in mxml file and then the Questions section under that are generated dynamically..

                                      I used the States to achieve that..

                                      Later I found that there is a very simple way to do the same..

                                      So I am converting the top part as well to be generated dynamically..

                                      The partial part of the new design can be downloaded from http://bijay.rungta.googlepages.com/AssessmentProgram.rar

                                      This produces the same Head part dynamically and is done using my own created package and classes in ActionScript. and it doesn't use States.

                                      I am going to clean the code further for code reuse by creating more functions and classes.

                                      Hope it will be helpful for you.

                                      Thanks,
                                      Bijay http://bijay.rungta.googlepages.com/_dev-2007-09-08_04-30.rar http://bijay.rungta.googlepages.com/AssessmentProgram.rar
                                      • 17. Re: How to Create a Dynamic Form
                                        bijayrungta Level 1
                                        Was this of any help buitwise??
                                        • 18. Re: How to Create a Dynamic Form
                                          bitwyse Level 1
                                          Hi bijayrungta,

                                          While I see and understand what your doing, it still isn't quite as dynamic as I was hoping for. Nor is the way I am doing it I suppose. If you reviewed my source code and saw how I am creating the HBox and VBox, that is truly dynamic in the sense I am creating them from a string. I'm not sure it's totally possible to do that for all field types. I do like they way you created your classes and implement them. I'm not sure which way I'll go with my form. I'll post it when I decide and finish it.

                                          I do have one questions. For some reason, when I use an HBox or VBox and add my formItems to them the alignment gets all goofy. I need to be able to put fields side by side at times not just top down. No matter what I try I can not get the alignment of all the labels to line up once I create an HBox and / or VBox.

                                          Any ideas?
                                          • 19. Re: How to Create a Dynamic Form
                                            bijayrungta Level 1
                                            bitwise,
                                            FormItem has ro be the immediate child of Form if you want it to be aligned properly as in my Form.

                                            If you have an HBox and VBox inside the Form and place the ForemItems inside these Boxes, it won't be displayed as you intend it to be.

                                            inside FormItem though you can have an HBox if you want to display two or three form controls/labels. for example if you need to show 3 combo box to collect Day, Month and the Year for a Date from the User.
                                            It will be like
                                            <mx:Form>
                                            <mx:FormItemlabel="Birth Day"><!-- Has to be immediate child of Form -->
                                            <mx:HBox>
                                            <mx:ComboBox id="selDay">
                                            <mx:ArrayCollection>
                                            <mx:Object label="1" data="1"/>
                                            <mx:Object label="2" data="2"/>
                                            <!-- other days -->
                                            </mx:ArrayCollection>
                                            </mx:ComboBox>
                                            <mx:ComboBox id="selMonth">
                                            <mx:ArrayCollection>
                                            <mx:Object label="1" data="1"/>
                                            <mx:Object label="2" data="2"/>
                                            <!-- other days -->
                                            </mx:ArrayCollection>
                                            </mx:ComboBox>
                                            <mx:ComboBox id="selYear">
                                            <mx:ArrayCollection>
                                            <mx:Object label="2007" data="2007"/>
                                            <mx:Object label="2006" data="2006"/>
                                            <!-- other days -->
                                            </mx:ArrayCollection>
                                            </mx:ComboBox>
                                            </mx:HBox>
                                            </mx:FormItem>
                                            </mx:Form>

                                            You can give width to your elements to align it properly or define some Style information/style classes to them.

                                            I am not sure which version of my code you saw. the second one is generated dynamically I guess.

                                            I have uploaded my latest files at http://bijay.rungta.googlepages.com/AssessmentProgram.rar you can have a look at it.
                                            • 20. Re: How to Create a Dynamic Form
                                              SWiiT Level 1
                                              Hi!
                                              I have a problem that is similar to this.
                                              I have create a form dynamic from a xml and now i what to send some text to some of the FormItems.

                                              in the code it looks like this

                                              -------------------------------------------------
                                              var fieldLabel:String = heading.@label; (this is from the xml)
                                              var obj:FormItem = new FormItem();
                                              var textField:TextInput = new TextInput();
                                              textField.name = "col"+i;
                                              textField.id = fieldLabel;
                                              obj.addChild(textField);
                                              userForm.addChild(obj);

                                              -------------------------------------------------

                                              I have tried to write
                                              col1.text = "the new text";
                                              but it say that col1 is undefined property.

                                              How can i do?