Flex ItemRenderer Issue - apache-flex

Am using Checkbox as ItemRenderer in tilelist. Am trying to setting
checkbox selected values through xml. I got the values perfectly.. but
checkbox could not bind the values(could not accept that). It's
automatically sets true for all checkboxes.
This is my xml
<PmhTreeAllow>
<PmhTreeAllowname id='1' label ='Allow Text' isField='false'/>
<PmhTreeAllowname id='2' label ='Document Link' isField='false'/>
<PmhTreeAllowname id='3' label ='Test Results Entry'isField='false'/>
<PmhTreeAllowname id='4' label ='Dummy' isField='false'/>
</PmhTreeAllow>
My Tilelist..
<mx:TileList id="tileList" width="160" height="100%" textAlign="left" horizontalScrollPolicy="off" verticalScrollPolicy="off" dataProvider="modelInstance.optionCollList}" columnCount="1" backgroundAlpha="0" borderStyle="none"itemRenderer="com.Frontend.views.treeStructure.myTileList" useRollOver="false" rowHeight="28" itemClick="tileItemClick(event)" columnWidth="150" selectedIndex="0" x="10" y="0">
Check box ItemRenderer..
<?xml version="1.0" encoding="utf-8"?>
<mx:CheckBox xmlns:mx="http://www.adobe.com/2006/mxml" label="{data.#label}" selected="data.#isField}"/>
Thanks in Advance
Ashok

http://www.switchonthecode.com/tutorials/flex-using-item-renderers
This will help u..

For performance reasons, it is considered a bad practice to use binding inside an itemRenderer. Instead listen to the FlexEvent.DATA_CHANGE and manually modify your values. I Bet doing so will solve your issue.
Try an itemRenderer like this:
<mx:CheckBox xmlns:mx="http://www.adobe.com/2006/mxml" label="{data.#label}" selected="data.#isField}" dataChange="onDataChange()">
<mx:Script><[[
public function onDataChange():void{
var dataAsXML = data as XML;
this.selected = data.#isField
this.label = data.#label
]]></mx:Script>
</mx:CheckBox>
I don't do a lot with XML, but I suspect that the XML properties will not bind because XML is not like an ActionScript object and therefore the "propertyChanged" Binding events do not exist on the XML object the same way they would be on an AS3 object.

Related

Adobe Air: need help transferring data from sqlite to components

I have successfully received data from sqlite. I see that the data appear in trace function, however I am having a problem with displaying these data correctly. I think it has something to do with binding objects. I must be missing something somewhere, so please correct where I am wrong. Also, this question is actually a continuation of Adobe Air: drag & drop grouped components
Anyway, here is my ItemRenderer:
<?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"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true">
<fx:Script>
[Bindable]
public var tree:TreeClass_Full;
[Bindable]
public var dataText:String = "empty";
public function setTest():void{
resultTextArea.text = "AAA";
}
</fx:Script>
<s:HGroup x="5" y="5" width="350" height="150" horizontalAlign="center" verticalAlign="middle">
<mx:Image id = "resultImage" width="100" height="100"/>
<s:TextArea id="resultTextArea" height="141" editable="false"
text = "{tree.Common_Name}"/>
</s:HGroup>
</s:ItemRenderer>
Here is the function which will be invoked after sqlite query is successful:
[Bindable]
public var dragDropLeft:ArrayCollection = new ArrayCollection();
[Bindable]
public var dragDropRight:ArrayCollection = new ArrayCollection();
protected function ResultFill():void
{
// TODO Auto-generated method stub
if (arr != null){
for (var i:int = 0; i < arr.length; ++i){
var tc:TreeClass_Full = arr[i];
var rr:resultRenderer = new resultRenderer();
rr.tree = tc;
trace("--Common Name:" + tc.Common_Name);
rr.dataText = tc.Common_Name;
rr.resultImage.source = tc.Picture1;
rr.resultTextArea.text = tc.Common_Name;
trace("----Common Name:" + rr.resultTextArea.text);
dragDropLeft.addItem(rr);
}
}
}
After the sqlite query is successful, the above function will be invoked. This is where I put in the information of my Object (my ItemClass from sqlite) into my ItemRenderer.
My ItemRenderer has two components: Image and TextArea. sqlite contains the respective image, which will be used for Image. For TextArea, all the displayable text from the database will be put there - meaning strings from multiple fields of the database will all be put together there. (but for now, I just want only one field in there, which is Common_Name)
After that, I put these ItemRenderers into my list (dragDropLeft, in this case). However, the data does not appear on the program. Yet, trace function outputs the text correctly.
I've tried a few things and I left some of the codes intact, and all of them yield the same result: the text in the TextArea does not change at all. What have I forget here?
UPDATE:
This code here covers the place that I used my Bindable ArrayCollection:
<s:HGroup width="100%" height="85%" verticalAlign="middle">
<s:List dataProvider="{dragDropLeft}" width = "45%" height = "95%"
dragEnabled="true" dragMoveEnabled="true" dropEnabled="true"
itemRenderer="resultRenderer"/>
<s:List dataProvider="{dragDropRight}" width = "45%" height = "95%"
dragEnabled="true" dragMoveEnabled="true" dropEnabled="true"
itemRenderer="resultRenderer"/>
</s:HGroup>
Basically, I tried to manipulate my ItemRenderer on my own by giving it values from sqlite, but from one of the commentors, it seems this is not correct. So how do we do this? How can we send in the data to the ItemRenderer objects that will be added in the list?
As I said in the comments: List is not a container. You cannot just add children to it. You should add data objects to its dataProvider. Basically the whole ResultFill method should be reduced to this:
dragDropLeft.dataProvider = new ArrayCollection(arr);
The ItemRenderers that represent this data will be created internally by the List component. Inside your custom ItemRenderer you can now access this data through the data property, so it would become something like this:
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
autoDrawBackground="true">
<s:HGroup x="5" y="5" width="350" height="150"
horizontalAlign="center" verticalAlign="middle">
<s:Image source="{data.Picture1}" width="100" height="100"/>
<s:TextArea text="{data.Common_Name}" height="141" editable="false" />
</s:HGroup>
</s:ItemRenderer>
Note that I am assuming that the properties of TreeClass_Full are bindable for this example.

Display HTML text in the Spark TextArea

The Below code is running well...
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" >
<fx:Declarations>
<mx:HTTPService id="httpRSS" url="http://www.petefreitag.com/rss/" resultFormat="object" />
</fx:Declarations>
<s:Panel id="reader" title="Blog Reader" width="500">
<mx:DataGrid width="485" id="entries" dataProvider="{httpRSS.lastResult.rss.channel.item}" click="{body.htmlText=httpRSS.lastResult.rss.channel.item[entries.selectedIndex].description}">
<mx:columns>
<mx:DataGridColumn dataField="title" headerText="TITLE"/>
<mx:DataGridColumn dataField="pubDate" headerText="Date"/>
</mx:columns>
</mx:DataGrid>
<mx:TextArea id="body" editable="false" width="485" x="3" y="142" height="155"/>
</s:Panel>
<s:Button label="Load" x="10" y="329" click="{httpRSS.send()}"/>
</s:Application>
But when Textarea is changed to spark Textrea like below
<s:TextArea id="body" editable="false" width="485" x="3" y="142" height="155"/>
Then htmlText doesn't support Spark Textarea. Hence produces error. How does one go about displaying HTML formatted text with spark Text Area Property.
If you're using the RichEditableText component instead, you can do it this way using the TextConverter class
var myStr:String = "I contain <b>html</b> tags!";
myRichEditableText.textFlow = TextConverter.importToFlow(myStr, TextConverter.TEXT_FIELD_HTML_FORMAT);
It can be also used in spark textArea:
var myStr:String = "I contain html tags!";
textAarea.textFlow = TextConverter.importToFlow(myStr, TextConverter.TEXT_FIELD_HTML_FORMAT);
This sometime will not work, if the HTML code is big and have some tags that can`t be rendered
TextFlowUtil.importFromString(yourHTMLString);
Check out the content property in the TextArea docs. Note the example at the end of the page.. it shows how to embed HTML.
body.textFlow = TextFlowUtil.importFromString(yourHTMLString);
I don't think you can. You should stick to using the Halo TextArea component or you should investigate the Text Layout Framework to accomplish your goals.
David Gassner's Flashbuilder 4 & Flex 4 has a section on this.
Take a look at TextFlowUtil. If you want to embed the HTML directly into the Spark TextArea (or RichText / RichEditableText), you can use the content tag as a child, then add the p or span tags thereafter - The supported HTML tags are part of the s namespace too.
Can also use :
(myTextArea.textDisplay as StyleableTextField).htmlText = text;

Binding custom components values

I have built a custom component using some containers and a TileList.
Now when I instantiate that component in my main Flex app, I want to get the value of the selected item in the tileList that the user clicks on. In other words, everytime the user clicks an item in the tileList, I want it to assign that selected value to a global application variable in the main flex app.
Any ideas how to do that?
Below is one way that you can listen to the change of TileList.selectedItem. I would recommend against putting this in a global variable, although if you must you could use a pattern like ModelLocator to do so.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical">
<mx:Script>
<![CDATA[
[Bindable] public var selectedItem:Object;
]]>
</mx:Script>
<mx:Binding source="listTile.selectedItem" destination="selectedItem"/>
<mx:Label text="{ selectedItem }"/>
<mx:TileList
id="listTile"
width="400"
height="300"
dataProvider="{ ['A','B','C'] }"/>
</mx:Application>

Flex: Components bound to empty ArrayCollection at load time don't render as expected when the ArrayCollection is updated

I'm new to Flex and am using TileList bound to an ArrayCollection. The array collection is empty at load time, and then updates with the results from am HTTPService call. The problem is that the item renderers aren't being rendered as expected, I'm guessing because there was no data when they were first rendered at load time. Here's simplified example:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var myList1:ArrayCollection = new ArrayCollection();
[Bindable]
public var myList2:ArrayCollection = new ArrayCollection([{item:"foo"}, {item:"bar"}]);
public function updateMyList():void
{
myList1.source = [{item:"foo"}, {item:"bar"}];
}
]]>
</mx:Script>
<mx:Button id="myButton" label="Update My List"
click="updateMyList();"/>
<mx:TileList dataProvider="{myList1}"
direction="vertical"
width="800" >
<mx:itemRenderer>
<mx:Component >
<mx:Canvas backgroundColor="yellow" >
<mx:Label text="{data.item}" width="800" />
</mx:Canvas>
</mx:Component>
</mx:itemRenderer>
</mx:TileList>
<!-- This one renders as expected -->
<mx:TileList dataProvider="{myList2}"
direction="vertical"
width="800" >
<mx:itemRenderer>
<mx:Component >
<mx:Canvas backgroundColor="yellow" >
<mx:Label text="{data.item}" width="800" />
</mx:Canvas>
</mx:Component>
</mx:itemRenderer>
</mx:TileList>
</mx:Application>
You will notice that the second TileList whose bindings has data at load time renders as expected (800px wide), bit the first TileList is rendered is not the correct width and has scrollbars around it.
Could anyone explain why this is happening or even provide some work arounds to avoid this?
Regards,
Chris
It's likely that this section is causing the problems:
public function updateMyList():void
{
myList1.source = [{item:"foo"}, {item:"bar"}];
}
From here:
source of data in the ArrayCollection.
The ArrayCollection object does not
represent any changes that you make
directly to the source array. Always
use the ICollectionView or IList
methods to modify the collection.
This property can be used as the
source for data binding. When this
property is modified, it dispatches
the listChanged event.
So I'd probably change the line to:
myList1= new ArrayCollection([{item:"foo"}, {item:"bar"}]);
http://livedocs.adobe.com/flex/3/langref/mx/controls/TileList.html
Check the API.
Set the columnWidth and rowHeight properties like this,
<mx:TileList dataProvider="{myList1}"
direction="vertical"
width="800" columnWidth="800" rowHeight="25">
There is probably a more "proper" way to do it, but that should get you started.

Is it safe to use a component reference in mxml

Consider the following radio button example.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
private function getRb1():RadioButton {
trace(rb1 == null);
return rb1;
}
]]>
</mx:Script>
<mx:VBox>
<mx:RadioButtonGroup **id="rbg" selection="{getRb1()}**"/>
<mx:RadioButton id="rb1" label="Radio Button 1" />
<mx:RadioButton id="rb2" label="Radio Button 2" />
<mx:RadioButton id="rb3" label="Radio Button 3" />
</mx:VBox>
</mx:Application>
The problem is that I can not refer to rb1 while defining RadioButtonGroup, rb1 is null at that time, but i can use the selectedValue to set the initial selction.
I was just wondering is this some special case or its not safe to refer to components in mxml in general.
Thanks,
I'm not quite sure what you're asking, but hopefully this'll answer your question -- from the Flex docs:
RadioButtonGroup.selectionContains a reference to the currently
selected RadioButton control in the
group. You can access the property in
ActionScript only; it is not settable
in MXML. Setting this property to null
deselects the currently selected
RadioButton control.
In general, though, making component references in MXML is totally fine; that's how effects are often handled, among many other things. For example:
<mx:Glow id="g" />
<mx:Label showEffect="{g}" />
However in your case, assuming you're having trouble setting the selected item, it might be because you haven't specified the group attribute on the radio buttons; omitting that detaches the group component from the individual buttons. Once you add that, you can bind the group's selection property using a Bindable variable containing a reference to a component, like so:
<mx:Script>
<![CDATA[
[Bindable]
private var selectedRadioButton:RadioButton;
private function this_creationComplete(event:Event):void
{
selectedRadioButton = rb1;
}
private function btn_click(event:Event):void
{
selectedRadioButton = rb2;
}
]]>
</mx:Script>
<mx:VBox>
<mx:RadioButtonGroup id="rbg" selection="{selectedRadioButton}" />
<mx:RadioButton id="rb1" group="{rbg}" label="Radio Button 1" />
<mx:RadioButton id="rb2" group="{rbg}" label="Radio Button 2" />
<mx:RadioButton id="rb3" group="{rbg}" label="Radio Button 3" />
<mx:Button label="Choose a Different Button" click="btn_click(event)" />
</mx:VBox>
Does this make sense? Hopefully it's not completely off the mark; post back and let me know and I'll try to help out as best I can.
Generally: just because a control was declared in MXML does not mean it is available at runtime (it might be deleted from AS, not created yet, not added to stage, therefore some properties are not available yet). This indicates it is not safe to access components at runtime and depend on values.

Resources