Hi all (again),

I guess using an existing post to create a new one simply by changing 
the subject wasn't a good idea.
It got stuck under a completely unrelated thread; So, sorry for the 
double post, but at least now I
will know that this isn't buried and ignored by accident...Here's my 
original post:
--------------------------------------------------------------------
I'm pretty sure that any answers for this one will help a lot of people,
since the basis of it crosses many complex business applications.

I have existing CF apps (Purchase Requests, Travel Requests, Request
Approvals, etc.) that contain many-to-many relationships, such as PR
Number > Charge Strings > Item/Costs, wherein the PR contains one or
more charge strings, and each charge string can have one or more items.
I am prototyping Flex versions, but I have come across a little (ha) bit
of a situation where I am not sure of the best method to proceed. I
have a actionscript form for creating a _new_ request, allowing the user
to add charge strings and associated items dynamically (stripped version
included below in case someone needs/wants to see how I did this).

Textually, a request being updated might look like this:

Request 1001

Charge String 1: CS: (combobox)
Item 1: Type (combobox) Cost (Number)...etc.
Item 2: Type (combobox) Cost (Number)...etc.
Item 3: Type (combobox) Cost (Number)...etc.

Charge String 2: (combobox)
Item 1: Type (combobox) Cost (Number)...etc.
Item 2: Type (combobox) Cost (Number)...etc.

Charge String 3: (combobox)
Item 1: Type (combobox) Cost (Number)...etc.

Note that Charge Strings and Items have unique IDs and there is a
relation between items and charge strings as well as items and the request.

However, a request also has to be available for updates, since they can
remain in draft status before being submitted for approvals. The
situation is this: Because of the possible many-to-many relationship
between charge strings and related items within a request, I'm not quite
sure of the best method of populating the form for updates.
Additionally, the user may add, remove or update items or an existing
charge string, and add new charge strings with new items

In CF, I only have to make 1 query to get the primary data I need, and I
can do a nested loop to create the form easily by checking for a change
in the charge string to know when to display the CS combobox and when to
display it's associated items. On update, we archive the old charge
string and item data and insert new rows into SQL Server, rather than
trying to determine which charge strings and/or items were updated.
This is for processing speed and the ability to recreate a request at
any point in time (using version numbers), the latter being necessary
for auditing the approval/rejection history of a request.

I am not sure if looping is the best method to use in Flex --
particularly since the containers are dynamic out of necessity -- nor am
I positive about the manner in which I should do this, in particular the
data population/combobox selected items.

(Btw, I started doing this with components, but actionscript was faster
for me to get it to work...I'll end up going back to that just for code
reuse but I like to see things work first :-)

----- charge string with estimated cost items code module (improvements
or hints appreciated as well) -----

<?xml version="1.0"

?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml 
<http://www.adobe.com/2006/mxml>"
creationComplete="addCS();">

<mx:Script>

<![CDATA[
import mx.controls.Alert;
import mx.controls.TextInput;
import mx.containers.HBox;
import mx.controls.ComboBox;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.utils.ArrayUtil;

//sample data for charge string combobox; would normally come from
an RO call
[Bindable]
public var CSCollection:ArrayCollection = new
ArrayCollection([{csUID: 1000, label: "CS1000"},{csUID: 1001, label:
"CS1001"},{csUID: 1002, label: "CS1002"}]);

//sample data for estimate type combobox; would normally come from
an RO call
[Bindable]
public var ETCollection:ArrayCollection = new
ArrayCollection([{etUID: 1000, label: 'Airfare'},{etUID: 1001, label:
'Meals'},{etUID: 1002, label: 'Other'}]);

public function addCS():void {
var newVBox:VBox = new VBox();
newVBox.setStyle( "borderColor", "#000000" );
newVBox.setStyle( "borderStyle", "solid" );
newVBox.setStyle("paddingBottom", 5);
newVBox.setStyle("paddingRight", 5);
newVBox.setStyle("paddingLeft", 5);
newVBox.setStyle("paddingTop", 5);
newVBox.percentWidth = 100;

var newCS:ComboBox = new ComboBox();
newCS.percentWidth = 100;
newCS.dataProvider = CSCollection;
var csCloseBtn:Button = new Button();
var csAddEstBtn:Button = new Button();

csCloseBtn.label = "Delete this Charge String and Associated
Estimates";

csCloseBtn.addEventListener(MouseEvent.CLICK,csCloseBtnClickListener);

csAddEstBtn.label = "Add Another Estimate to this Charge String";

csAddEstBtn.addEventListener(MouseEvent.CLICK,csAddEstBtnClickListener);

var newbtnHbox3:HBox = new HBox();

newbtnHbox3.addChild(newCS);
newbtnHbox3.addChild(csCloseBtn);
newbtnHbox3.addChild(csAddEstBtn);

newVBox.addChild(newbtnHbox3);

var eparent:Object = newVBox;
addEst(eparent);
csbox.addChild(newVBox);
}


public function csCloseBtnClickListener(e:Event):void
{
var ncs:Number = csbox.numChildren;

if (ncs != 1)
{
csbox.removeChild(e.target.parent.parent);
}
else
{
Alert.show("Minimum of One Charge String Required");
}
}

public function csAddEstBtnClickListener(e:Event):void
{
addEst(e.target.parent.parent);
}

public function estCloseBtnClickListener(e:Event):void {
//set a var indicating the hbox that is the estimate row object...
var thisestChild:DisplayObject = e.target.parent.parent;
//set a var indicating the parent csbox that contains the
estimate row object
var thiscsboxDO:Object = e.target.parent.parent.parent;
//determine number of estimates: total children in csbox - 1 cs
& button row
var nest:Number = e.target.parent.parent.parent.numChildren - 1;

if (nest != 1)
{
thiscsboxDO.removeChild(thisestChild);
}
else
{
Alert.show("Minimum of One Estimate per Charge String Required");
}
}

public function addEst(eparent:Object):void
{
var newVbox2:VBox = new VBox();
newVbox2.percentWidth = 50;
var newEst2 : TextInput = new TextInput();
newEst2.text = "(estimated cost here)"
var newcbEst:ComboBox = new ComboBox();
newcbEst.dataProvider = ETCollection;
var estCloseBtn:Button = new Button();
estCloseBtn.label = "Delete this Estimate";

estCloseBtn.addEventListener(MouseEvent.CLICK,estCloseBtnClickListener);

var newHbox3:HBox = new HBox();
newHbox3.addChild(newcbEst);
newHbox3.addChild(newEst2);
newHbox3.addChild(estCloseBtn);
newVbox2.addChild(newHbox3);

eparent.addChild(newVbox2);
}

]]>

</mx:Script>

<mx:Canvas height="100%" width="100%" id="csestcanvas">

<mx:Panel title="Charge Strings and Estimated Costs" id="CSEstPanel"
backgroundColor="#eeeeee" width="90%" height="{csestcanvas.height}"
paddingTop="10" paddingLeft="10" paddingRight="10"
paddingBottom="10">

<mx:Button id="AddCS" label="Add a New Charge String"
click="addCS()"/>

<mx:VBox width="100%" id="csbox" >
<!-- this is where all AS containers/controls are added -->
</mx:VBox>

</mx:Panel>

</mx:Canvas>

</mx:Application>

Reply via email to