How to populate flex combo box with xml data - apache-flex

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.

Related

Access data in custom component in Flex

I am new to Flex so pardon me if my questions are quite basic. I have searched a lot before posting here, might be I was not looking in the right direction. Please redirect me to the path that leads to the solution of the problem. I really appreciate any help that I can get.
I'm following this video tutorial. (I was creating Mobile Project not a simple Flex project like in video)
http://www.gotoandlearn.com/play.php?id=100
All was going fine, until the tutor wanted to add custom component in the application. He added the HBox which I couldn't find in Flash Builder 4.6 so I added HGroup instead in my new component. Now when I want to use the data that was fetched in the parent component in custom component it gives me error. Here is the code and their file names.
File: SearchHomeView.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="Twitter Search">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<s:HTTPService result="onResult(event)" id="service" url="http://search.twitter.com/search.atom?q=adobe">
</s:HTTPService>
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.utils.flash_proxy;
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[Bindable]
private var ac:ArrayCollection;
private function onResult(event:ResultEvent):void
{
ac = event.result.feed.entry as ArrayCollection;
trace(data);
trace(ac);
}
private function doSearch(event:MouseEvent):void
{
//service.url = "http://search.twitter.com/search.atom?q=" + tearch.text;
service.url = "http://search.twitter.com/search.atom?q=adobe";
service.send();
}
]]>
</fx:Script>
<s:TextInput x="25" y="26" width="146" id="tearch"/>
<s:Button x="224" y="26" height="33" label="Search" click="doSearch(event)" />
<s:List dataProvider="{ac}" itemRenderer="tweet" x="25" y="92" width="274" height="278"></s:List>
</s:View>
File: tweet.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:HGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" width="400" height="300">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Image width="50" height="50" source="{parentDocument.data.link.getItemAt('1').href}">
</s:Image>
<s:TextBase width="100%" text="">
</s:TextBase>
</s:HGroup>
When I use source to be source="{parentDocument.data.link.getItemAt('1').href} ... it removes the error, but displays nothing on the resulting app.
When I use source to besource="{data.link[1].href} ... it gives the error,
Multiple markers at this line:
-1120: Access of undefined property data.
-parentDocument
What needs to be done to use the item renderer right in custom component ? Please tell me the solution to it... I'm stuck on it for quite a few time.
Your component Tweet.mxml should extend an ItemRenderer.
In Flex 3 many components could be used as item renderers, that old (Flex 3) HBox component you saw in the video works as an item renderer b/c it has a data property.
As part of Flex 4's "pay as you go" approach, the container classes (Group, HGroup, etc) do not support being used directly as item renderers. As a result HGroup doesn't have a data property.
Try making Tweet.mxml look something like this:
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" width="400" height="300">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:HorizontalLayout />
</s:layout>
<!-- Typically, the dataProvider of your List is an array of objects of the same
type. So each item renderer that is on screen has it's data property populated
with one of these items. You can then craft an MXML document like this that
uses the properties of your array element. You're going to need to use the
right expression that finds the image source in the data item. If you really
want to be rendering the array data.link, pass that data w/an ArrayCollection
to the list instead ... it's hard to advise here w/out knowing what your data
looks like. -->
<s:Image width="50" height="50" source="{data.link.getItemAt('1').href}" />
<s:StyleableTextField width="100%" text="" />
</s:ItemRenderer>
The changes I'm making are:
extend ItemRenderer
replace HGroup's layout by using the HorizontalLayout in the renderer
using the data property of the renderer for the source of the image (use the data property to populate all of the dynamic parts of the renderer (like the text field)
using a StyleableTextField, optimized text for mobile
In your onResult event handler - be careful to check that you are in fact assigning all items into the arraycollection - If feed.entry is not explicitly an ArrayCollection you will need to iterate the list (assuming this an xmllist because it looks like an RSS feed)...
So instead:
protected function onResult(event:ResultEvent):void
{
if (!ac) ac = new ArrayCollection();
for each (var entry:XML in event.result.feed..entry)
{
ac.addItem(entry);
}
}
As for the ItemRenderer, you have a couple of different options...
ItemRenderer - as suggested by #Sunil, this is the 'base' class of renderers to use in spark based lists.
DataGroup - this is similar to a Group where you specify a layout, but it creates "renderers" - anything with a 'data' property using a dataprovider, the key to this one though is there is no virtualization it just creates all of them.
It gets more complicated than this when you switch to a DataGrid...

AddItemAt() of arraycollection is not working in flex

I am trying to add an item in arraycollection which is sorted and filtered using addItemAt().
But addItemAt() is not adding item to the specified index.
Do anyone knows the solution for the above problem.
I am trying to add an item in arraycollection which is sorted and
filtered
If the collection is sorted, the filter will automatically be refreshed when you add a new item to it. So, the index you add your item may not the index were your item ends up. It depends entirely on the sorting algorithm.
You can remove the sort to lock your new item at the index you specify. Off the top of my head, do this:
arrayCollection.sort = null;
arrayCollection.refresh();
I'm pretty sure the same concept applies to filtering. If you have a filter applied to a collection, the new item needs to match the filter criteria or else it will not show up in the collection until the filter is removed.
I had a problem similiar to this only in Flex 3 and with a sorted ArrayCollection. If you scour, you will find that addItemAt does not work with a sorted ArrayCollection (and prolly not filtered? don't know). The item will be added according to the sort criteria.
However, I needed a sorted ArrayCollection (alpha) with a "Select All" option at the top, so this is how I proceeded:
An array can be sorted easily (array.sort), so I first created an Array. Then I Looped the ArrayCollection and added the item from the ArrayCollection on which I wished to sort to the array. This new array was then sorted.
The newly sorted array was looped and within this loop, the ArrayCollection was looped again. If a match was found on the sorted item, I added this object to a new ArrayCollection but also created a new property of the object added called "sortOrder" which was set to the loop count.
Next the "Select All" Object was created and its sortOrder set to -1.
Finally, numeric sort was created on the sortOrder field of the ArrayCollection and Voila -- it worked.
Perhaps someone has a more elegant solution but I was in a hurry and it worked darn it.
Hope this helps someone.
addItemAt() is adding item to the specified index.
*for example:
*
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var myArray:ArrayCollection= new ArrayCollection([
{student:'one',subject:'2'},
{student:'two',subject:'4'},
{student:'three',subject:'5'},
{student:'four',subject:'6'}
]);
protected function addArrayCollectioninRuntime(event:MouseEvent):void
{
myArray.addItemAt({student:nameTxtinput.text,subject:subjectTxtinput.text},3);
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:Form>
<s:FormItem label="Student Name :">
<s:TextInput id="nameTxtinput"/>
</s:FormItem>
<s:FormItem label="Student Subject :">
<s:TextInput id="subjectTxtinput" />
</s:FormItem>
<s:Button label="Submit" click="addArrayCollectioninRuntime(event)"/>
</s:Form>
<mx:DataGrid dataProvider="{myArray}" id="dGrid" >
<mx:columns>
<mx:DataGridColumn dataField="student" id="stud"/>
<mx:DataGridColumn dataField="subject" id="sub"/>
</mx:columns>
</mx:DataGrid>

Adding a child to a VBox component (FLEX)

First of all I wanted to thank in advance to everyone that reads this post.
I'm having a problem when adding a child to a VBox component. Is it not the same thing?:
List Item:
<mx:Script>
<![CDATA[
public function addChildren():void {
var f:FaqItem=new FaqItem();
f.id="newUsersAssistance";
this.cont.addChild(f);
}
]]>
</mx:Script>
<mx:VBox id="cont" width="100%" borderThickness="0" verticalGap="0"/>
and:
<mx:VBox id="cont" width="100%" borderThickness="0" verticalGap="0">
<view:FaqItem id="newUsersAssistance" />
</mx:VBox>
I am injecting two properties (question and answer) to the FaqItem component from an auxiliar file (using BabelFX) that depends on the id of the FaqItem, but it is only working when I choose the second option. If I use the first option, I get a child but with the text in question and answer fields is empty. I need to use the first option.
Is there anything I am doing wrong?
Thanks again for everything
Kind Regards
i don't think you will be able use the id property of the dynamically added component to do Injection. I suggest you keep some bindable variables to bind the value to the dynamic FaqItem.

Disable warning only in one place

In an MXML code
<fx:Script>
public var data:ArrayCollection = new ArrayCollection();
</fx:Script>
<s:DataGroup dataProvider="{data}" />
I'm getting a warning:
Data binding will not be able to detect assignments to "data"
I know that the data provider will be never changed in this case, and want to suppress this warning in this case, but I don't want to completely disable it, -show-binding-options=false in all project is not an option.
How to disable a warning only in one place? Disabling for the whole file is not so good, but acceptable.
How about just making your data variable bindable? Something like:
<fx:Script>
[Bindable]
public var data:ArrayCollection = new ArrayCollection();
</fx:Script>
<s:DataGroup dataProvider="{data}" />
Instead of using <fx:Script></fx:Script> you could use <fx:Declarations></fx:Declarations>. Any object declared in that MXML element is bindable implicitly. Here's how your code will look like then:
<fx:Declarations>
<s:ArrayCollection id="data" />
</fx:Declarations>
<s:DataGroup dataProvider="{data}" />
Additionally it becomes much more readable and there's no mix of ActionScript and MXML. Because your collection is declared as public it makes difference whether to use ActionScript with [Bindable] or using MXML.
BTW, a general recommendation for cleaner code is to separate ActionScript completely from MXML. For instance in my projects I create a separate ActionScript file for each MXML component in the form <NameOfComponent>Includes.as.

Can i create multiple itemrenderer for a datagrid column in flex?

I actually wanted to create an itemrenderer which will contain below code :
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="0" height="0" >
<mx:Label text="{data.xval}" />
<mx:Spacer width="100%" />
<mx:Image source="edit.gif" width="16" toolTip="Edit" />
</mx:HBox>
Now when i click on the image datgrid column should be editable, for that i am using a textinput as an itemeditor. Now i also want to highlight all those cell for this datagrid column which are having data more than 8 characters. I am able to do this separately using 2 different itemrenderers. but i want to get this all together. Can anyone pls help me to do this? Can we have multiple itemrenderer for any datagrid column?
Please let me know if my question is not clear to you?
Thanking you in advance.
One way to do it is to create a function that returns the name of the style that you want to use for highlighting, and call that function by databinding to the style property of your HBox. For example, if you had one css class named highlight and one named normal, you could use this function:
public function highlight(data:String):String
{
if(data.length >= 8)
{
return "highlight";
}
return "normal";
}
And call it like this:
<mx:HBox styleName="{highlight(data.xval)}">
...
</mx:HBox>

Resources