Passing array from flex to php - apache-flex

I have a TextInput and a List in my application. I want to send the information written in TextInput and the names of the selected options from the list to a php file.
Following HTTPService sends the TextInput's text and the indices of selected items from list finely to a php file but the selectedItems is not working as i expected. It does not send the names of the selected items
<mx:HTTPService id="configureService" url="configure.php" resultFormat="text" method="POST">
<mx:request xmlns="">
<textInput>
{textInput.text}
</textInput>
<selectedFoodNames>
{foodList.selectedItems.join(",")} <!-- Problem in this LOC -->
</selectedFoodNames>
<selectedFoodIndices>
{foodList.selectedIndices.join(",")}
</selectedFoodIndices>
</mx:request>
</mx:HTTPService>
Now, my php file results:
echo $_POST['textInput']; //Output the right answer
echo $_POST['selectedFoodNames']; //Outputs: "[object Object],[object Object],[object Object]" if three items are selected from the list
echo $_POST['selectedFoodIndices']; //Outputs the indices of selected items separated by comma
The list look like:
<mx:List id="foodList" x="26.95" y="54" width="231.55" height="236.9" allowMultipleSelection="true">
<mx:dataProvider>
<mx:Array>
<mx:Object id="Sugar" label="Sugar" data="#FF0000"/>
<mx:Object id="Salt" label="Salt" data="#00FF00"/>
<mx:Object id="Pepper" label="Pepper" data="#0000FF"/>
</mx:Array>
</mx:dataProvider>
Is there a way i can send the labels of the elements in list?

You'll need to write a function to make a list from the objects.
public static function selectedItemsToLabels(list:List):String {
var a:Array = [];
for each(var o:Object in list.selectedItems) {
a.push(o.label);
}
return a.join(",");
}
This is a static function but you can make it a member of a List if you want to extend that class.

I'm not sure if you want to get another framework involved, but I've used Zend AMF as a solution to such problems. It lets you pass Flex and PHP objects back and forth without having to manually create or parse XML intermediaries.
You can read more at:
http://framework.zend.com/manual/en/zend.amf.html

Related

How to pass column value to dataTipFunction in AdvancedDataGridColumn Flex

Flex Experts,
I am a newbie here. I am trying to create a conditional tool tip for my contact detail screen. If the contact has 'special-roles' like 'ABC, XYZ' then the tool tip should appear otherwise not. We have AdvancedDataGridColumn and using dataTipFunction to display the tool tip.
I am passing, values of roles & 'special-roles' in dataProvider for all contact objects.
I need to write tool-tip condition for every row(every contact). I am unable to write the condition in dataTipFunction as it has access to only 'item' object. I tried trace and Alert on 'item', but screen goes blank.
I have also tried "showDataTips" which accepts boolean but to no avail. I need a way to pass current row values (all columns) to a function from AdvancedDataGridColumn.
Here is the snapshot of my code. Any help is very much appreciated :)
<view:CopyPasteDataGrid id="contactsHolder"
width="100%"
height="100%"
displayDisclosureIcon="true"
variableRowHeight="true"
defaultLeafIcon="{null}"
folderClosedIcon="{null}"
folderOpenIcon="{null}"
useRollOver="true"
selectable="true"
styleName="PortfolioAdvanced"
designViewDataType="tree"
horizontalCenter="true"
verticalGridLines="false"
horizontalScrollPolicy="off"
dataProvider="{contactDetails}"
headerRelease="onHeaderRelease(event)">
<view:columns>
<mx:AdvancedDataGridColumn dataField="lastName"
sortCompareFunction="lastNameCompare"
headerText="{ApplicationConstants.LAST_NAME_HEADER}"
showDataTips="true" dataTipFunction="buildToolTipForContact"
width="100"/>
<view:rendererProviders>
<mx:AdvancedDataGridRendererProvider dataField="projectContacts"
renderer="com.ihg.hom.common.view.components.render.ContactsRenderer"
columnIndex="0"
columnSpan="0"/>
</view:rendererProviders>
</view:CopyPasteDataGrid>
private function buildToolTipForContact(item:Object):String
{
var myString:String="";
return "hello";
}
I have resolved it using different approach. I used label function. It has access to column object and based current object roles I am setting tool tip. Here is the code for reference.
<mx:AdvancedDataGridColumn dataField="role" sortable="{isRoleSortable}"
labelFunction="getRole"
headerText="Role" sortCompareFunction="sortRole" showDataTips="true" dataTipFunction="buildToolTipForContact"
width="120"/>
private var hasRole:Boolean=false;
private function getRole(item:Object):String
{
// extra code
if(currentRoles.indexOf(specialRole)!=-1)
{
hasRole=true;
}
}
private function buildToolTipForContact(item:Object):String
{
var myStr:String="";
if(hasRole){
myStr="Special Role";
}
return myStr;
}

How to populate flex combo box with xml data

here is the xml data :
<root>
<recommendedMaterials>
<value label="Aluminium" data="0" />
<value label="Iron" data="0" />
</recommendedMaterials>
</root
My code :
<mx:Script>
<![CDATA[
public function populateRecommendedMaterials(xml_val:XML)
{
materials_Cmb.dataProvider=(xml_val.recommendedMaterials);
}
]]>
</mx:Script>
<mx:ComboBox x="212" y="164" id="materials_Cmb" dataProvider="materialsCmb_Dp"></mx:ComboBox>
</mx:Canvas>
The problem is that the whole xml gets populated. I just want the labels. :(
There are two approaches here, depending on what you need. In either case the data you want are the children of the recommendedMaterials node, not the node itself (which is what you did).
materials_Cmb.dataProvider =
new XMLListCollection(xml_val.recommendedMaterials.children());
This should already do the trick. Note that I wrapped the XMLList in an XMLListCollection: this is not strictly necessary with the mx:ComboBox, because it will do the same internally, but for Spark components it would be mandatory.
Another more concise solution would be to just find all the 'value' nodes, but I don't know whether that approach fits your bill.
materials_Cmb.dataProvider =
new XMLListCollection(xml_val..value);
Also don't forget to assign the correct 'labelField' in the ComboBox:
<s:ComboBox labelField="#label" />
The # sign represents an XML attribute.

Flex Datagrid within repeater - Data bind warning

In my Flex app I am using a repeater to show a report on my database data. On this report the user can "drill-down" on the data to show more detail. In order to make this easier on the eye I have a header label and then a datagrid within the repeater.
Whilst this works perfectly, because the dataprovider for the datagrid comes from an array in the repeaters dataprovider, it is causing the following warning:
Data binding will not be able to detect assignments to "report"
The warning is for this line:
<mx:DataGrid id="dgReport" dataProvider="{rptReport.currentItem.report}" rowCount="{rptReport.currentItem.report.length}">
Below is my code, if anyone has any suggestions for how I can get rid of the warning/do this properly they will be most welcome!
<mx:Script>
<![CDATA[
[Bindable] private var reportProvider;
private function report_Handler(event:ResultEvent):void {
// Temp variables
var currentHeader:String = "";
var previousHeader:String = "";
// Retrieve PHP array
var reportPHP:Array = ArrayUtil.toArray(event.result);
// Create Flex array
var reportFlex:Array = [];
var reportFlex_dataGrid:Array = [];
// Loop through PHP array
for(var i:int = 0; i < reportPHP.length; i++) {
// Retrieve current header
currentHeader = reportPHP[i].header;
// Clear array
if (currentHeader != previousHeader) {
reportFlex_dataGrid = [];
}
reportFlex_dataGrid.push({column1:reportPHP[i].column1, column2:reportPHP[i].column2, column3:reportPHP[i].column3});
}
// Add to repeater array
if (currentHeader != previousHeader) {
// Add to array
reportFlex.push({header:reportPHP[i].header, report:reportFlex_dataGrid});
}
// Store previous headers
previousHeader = reportPHP[i].header;
// Add to combobox data provider
reportProvider = new ArrayCollection(reportFlex);
}
]]>
</mx:Script>
<mx:Repeater id="rptReport" dataProvider="{reportProvider}">
<mx:VBox>
<mx:Spacer height="5"/>
<mx:Label id="lblHeader" text="{rptReport.currentItem.header}"/>
<mx:DataGrid id="dgReport" dataProvider="{rptReport.currentItem.report}" rowCount="{rptReport.currentItem.report.length}">
<mx:columns>
<mx:DataGridColumn headerText="Column1" dataField="column1"/>
<mx:DataGridColumn headerText="Column2" dataField="column2"/>
<mx:DataGridColumn headerText="Column3" dataField="column3"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:Repeater>
Data binding will not be able to detect assignments to "report"
Your dataProvider is rptReport.currentItem.report. Of this, rptReport, being an mxml element, is Bindable. The currentItem property of the Repeater component is also declared to be Bindable. The report property of the current item is not bindable - current item itself is just an object. Through this warning Flex is saying that if you alter the report of an already assigned object to something else, it won't be automatically reflected in the data grid.
In most cases you can safely ignore this type of warnings.
When you say x="{a.b.c.d}" in mxml, the guarantee is that flex will detect changes made to any of the four items in the chain (a, b, c and d) and update the value of x. In other words, x will change when a or a.b or b.c or c.d is changed. For this to work, Flex expects that all those four are declared bindable. If it finds any of these items to be not bindable, it will throw a warning. A property is bindable if it was declared using mxml or if it was declared with the [Bindable] metadata tag in ActionScript.
In most cases, one would be interested only in the changes to a or a.b. In your example, changes happen only when HTTPService is resend, in which case the dataProvider itself will change.
Dude, a little off-topic, but having a grid in a repeater sounds really busy. If you want to have a drill-down, pop it up or put it in a pane that's only visible in that mode.
Visually, the repeater is a pattern which the user can internalize. A grid inside that pattern is a lot harder to deal with. Scrolling the grid vs. scrolling the repeater will likely be frustrating, let alone Tab navigation.
Logistically, you are creating a lot of in-memory UI. I would worry about performance.
Consider using a List with a custom Item renderer instead of a repeater. I still would not put a grid in there, but it's worth the effort.
Cheers

Problem with setting the xml dataprovider for combo box

I am trying to get the drop down list of combobox by using a php file. That php file returns an xml string which has been used as data provider for combobox.
I followed this thread too but in vain.
Details
I have set the creationComplete attribute of mx:Application to init(). In the init() function i have sent the following HTTPService
<mx:HTTPService id="interfaces" url="interfaces.php" resultFormat="e4x" method="POST">
</mx:HTTPService>
Combo Box:
Update:
The xml should look like
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<ifaces>
<iface>
<option>eth0</option>
</iface>
<iface>
<option>eth1</option>
</iface>
</ifaces>
but if i execute interfaces.php in browser the only things that gets display is
eth0eth1
whereas i am echoing the string that contains whole xml data. Shouldn't whole xml type of string display? :(
The problem is that ifaces is the root element of your XML, so interfaces.lastResult == ifaces. So the XMLList you want is interfaces.lastResult.iface.
This is a whole main class that works for me:
`<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
initialize="{interfaces.send();}">
<mx:HTTPService id="interfaces" url="interfaces.xml" resultFormat="e4x" method="POST">
</mx:HTTPService>
<mx:ComboBox dataProvider="{interfaces.lastResult.iface}" labelField="option"/>
</mx:Application>`

Flex : How to display a DataGrid selectedItem's details in a Form

Sorry for this long post. The question is however small but requires full detail. Thanks for reading and helping :)
I used HTTPService POST method to call a php file that returns me an xml type of result like
<user>
<name>jones</name>
<age>34</age>
</user>
This result is obtained after the php files queries a database. The database contain other information too like (height, gender, education and address)
Now i have a DataGrid (having two columns: NAME and AGE) and a Form below the DataGrid. I have displayed the above mentioned xml data in the DataGrid using the dataprovider="{userRequest.lastResult.User}" attribute.
I now want to use the itemclick=itemClickEvent(event) so that when a user click on a row of the DataGrid other information related to the clicked row like (height, gender, education etc) may appear in the form which is placed below the DataGrid in the GUI. For now my itemClickEvent, look like:
private function itemClickEvent(event:ListEvent):void
{
clickRow.text=String(event.rowIndex);
//Don't know what should i assign to following labels...
//height.text=
//gender.text=
//edu.text=
}
Form's structure:
Is there any way i may access the xml data from the itemClickEvent function? given that the DataGrid structure header look like
<mx:DataGrid id="dgUserRequest" dataProvider="{userRequest.lastResult.user}" x="28.7" y="36" width="525" height="149" itemClick="itemClickEvent(event);">
and the HTTPService header look like
<mx:HTTPService id="userRequest" url="request.php" method=POST">
<mx:request xmlns="">
<getResult>send</getResult>
</mx:request>
</mx:HTTPService>
The concerned part of my php file is:
if($_POST['getResult'] == 'send')
{
$Result = mysql_query("SELECT * FROM userInfo" );
$Return = "<userInfo>";
while ( $row = mysql_fetch_object( $Result ) )
{
$Return .= "<user><name>".$row->name."</name><age>".$row->age."</age><height>". $row->height."</height><gender>". $row->gender."</gender><education>".$row->education."</education></user>";
}
$Return .= "</userInfo>";
mysql_free_result( $Result );
print ($Return);
}
If you are using userRequest.lastResult.user.name as the dataProvider for the data grid, what are your dataFields in the name and age columns?
There is another easy way to do this. Let's say the xml structure is something like:
<someRootTag>
<user>
<name>jones</name>
<age>34</age>
<height>180cm</height>
</user>
<user>
<name>john</name>
<age>4</age>
<height>100cm</height>
</user>
<!--more <user/> tags-->
</someRootTag>
You can achieve this using data binding. Note that resultFormat of HTTPService has been changed to e4x from the default object
<mx:HTTPService id="service" url="data.xml" resultFormat="e4x"/>
<mx:DataGrid id="dg" dataProvider="{service.lastResult.user}">
<mx:columns>
<mx:DataGridColumn dataField="name"/>
<mx:DataGridColumn dataField="age"/>
</mx:columns>
</mx:DataGrid>
<mx:Form>
<mx:FormItem label="Name">
<mx:TextInput text="{dg.selectedItem.name}"/>
</mx:FormItem>
<mx:FormItem label="Age">
<mx:TextInput text="{dg.selectedItem.age}"/>
</mx:FormItem>
<mx:FormItem label="Height">
<mx:TextInput text="{dg.selectedItem.height}"/>
</mx:FormItem>
</mx:Form>
The only AS code you need is to call service.send() from creationComplete of the application.

Resources