Grid itemrenderer messup while scrolling - actionscript-3

I have one list which have Datagrid as itemRenderer like:
<s:List id="cList" itemRenderer="views.renderers.DGridItemRenderer"
dataProvider="{sList}" useVirtualLayout="false"/>
And ItemRenderer Datagrid is like:
<s:DataGrid id="cDataGrid" width="100%" height="100%" editable="true" >
<s:columns>
<mx:ArrayList>
<mx:source>
<s:GridColumn width="40" headerText="Name" dataField="name" editable="false"/>
<s:GridColumn width="40" headerText="class" dataField="class" editable="false" />
<s:GridColumn width="60" headerText="age" dataField="age" editable="true"/>
<s:GridColumn width="60" headerText="SLight" editable="false" itemRenderer="views.renderers.SLColorStatusRenderer"/>
</mx:source>
</mx:ArrayList>
</s:columns>
</s:DataGrid>
Now Slight gridColumn have following GridItemRenderer which have icon :
<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" verticalCenter="0" clipAndEnableScrolling="true">
<fx:Script>
<![CDATA[
override public function prepare(hasBeenRecycled:Boolean):void {
if(data.age < 18 && data.age > 0)
{
imgStatus.source = ImageProvider.redIcon;
}
else if(data.age >= 18)
{
imgStatus.source = ImageProvider.greenIcon;
}
]]>
</fx:Script>
<s:Image id="imgStatus" width="21" height="21" buttonMode="true" horizontalCenter="0" verticalCenter="0" />
</s:GridItemRenderer>
SLight column contained Red/Green icon depend on data of age. Age value should be editable in datagrid.
If Age lessthan 18 then red else green icon.
Now, My issue is that When i scroll datagid, icon will mess-up. Icon will display in any record wheather there is age or not.
When load first time all icon looks good. But when i scroll then only mess-up icon and chnage their position.
I use useVirtualLayout="false" for list and clipAndEnableScrolling="true" for itemrenderer but still i can't solve it.
I found lot but didn't get any proper solution.
Edit:
If age less then 18 then red, Else if age greater 18 then green. Other wise if not age defined then blank.
My issue is when i scroll then blank row will also display icon. and red icon row will change to green and green to red randomly. All messup.
First it shows like following. (it's correct):
After when i scroll datagrid it change to following. (it's in-correct)

Your problem is that you're not handling itemrenderer recycling properly, given that age is not always set. You'd be okay if your data always had an age value. As it is, your code doesn't have a way to blank out the imgStatus object -- it just leaves whatever icon was already there if age is null or -1.
Change your code to the following:
if(data.age < 18 && data.age > 0)
{
imgStatus.source = ImageProvider.redIcon;
imgStatus.visible = true;
}
else if(data.age >= 18)
{
imgStatus.source = ImageProvider.greenIcon;
imgStatus.visible = true;
}
else
{
//You could use the following line instead if you have a "clear icon" defined.
//imgStatus.source = ImageProvider.clearIcon;
imgStatus.visible = false;
}

Related

Flex - Set Editable propertie programmatically for a GridColumn

Is it possible to dynamically change the property "Editable" of a GridColumn regarding the value of an another Column.
Once I have filled my dataProvider I would like to loop ont he dataGrid rows, but I can't find how to it ?
Thanks.
I tried
editable="{if (data['Type']=='foo'){return true;} else {return false;}}"
but build failed.
How about to use itemRenderer?
<s:GridColumn dataField="Type" width="100" editable="false"/>
<s:GridColumn dataField="Name" width="100" editable="false"/>
<s:GridColumn dataField="Score" width="100" editable="true" rendererIsEditable="true">
<s:itemRenderer>
<fx:Component>
<s:GridItemRenderer>
<fx:Script>
<![CDATA[
override public function set data(value:Object):void {
if (value != null && value != "") {
super.data = value;
if (super.data["Type"] == "foo"){
somefield.editable = true;
}
else{
somefield.editable = false;
}
}
}
]]>
</fx:Script>
<s:TextInput id="somefield" text="{data.Score}"/>
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:GridColumn>
Run example on wonderfl
Thanks. In fact I use ItemEditor and/or ItemRenderer for some columns.
In my case I have
<s:GridColumn id="gcAmountEUR" labelFunction="amountFormat" dataField="AmountEUR" headerText="AMOUNT EUR" width="80" itemEditor="components.gieOrderAmount">
<s:itemRenderer>
<fx:Component>
<s:DefaultGridItemRenderer textAlign="right" />
</fx:Component>
</s:itemRenderer>
</s:GridColumn>
<s:GridColumn dataField="CurrencyCode" headerText="CURRENCY" width="50" itemEditor="components.gieOrderCurrency" >
</s:GridColumn>
<s:GridColumn id="gcAmount" labelFunction="amountFormat" dataField="Amount" headerText="AMOUNT" width="120" itemEditor="components.gieOrderAmount">
<s:itemRenderer>
<fx:Component>
<s:DefaultGridItemRenderer textAlign="right" />
</fx:Component>
</s:itemRenderer>
</s:GridColumn>
The datagrig has the property editable="true".
By default the column AmountEUR is Editable an the column Amount is not.
But if for a row the value of Currency is not "" so I want AmountEUR to be not Editable and Amount to be Editable. So I would like to programmatically change the property Editable of the column for each row.
So I would like to parse the datagrid to change, for each row, the property value "Editable" of AmountEUR and Amount if Currency is not Empty.
But perhaps it is not the good way to do it ?
I hope I made myself clear.
Antoine.

Spark List: ensureIndexIsVisible with expanding list itemRenderer

I have a Spark List with an expanding itemRenderer (snippet of it below). It works very well but I am struggling to display the fully expanded list item when calling ensureIndexIsVisible. I've tried various things with validate/invalidate to try to force the List to take the expanded item size into account but either I am doing it wrong or the List component isn't built to handle this.
In the image below, I've called myList.ensureIndexIsVisible(7);Item 7 is expanded and the header scrolled to be visible but most of the expanded item is offscreen.
Anyone know a way to address this?
Update: If the List is specified to have useVirtualLayout="false" then the following works:
myList.validateNow();
myList.ensureIndexIsVisible(expandIndex);
but of course if there are a lot of cells in the List instance then this is a problem.
protected function expandOne_clickHandler(event:MouseEvent):void
{
var expandIndex:Number = Number(expandTarget.text);
data.getItemAt(expandIndex).selected = true;
myList.invalidateDisplayList();
myList.ensureIndexIsVisible(expandIndex);
myList.validateNow();
}
List itemRenderer:
<s:CheckBox id="eventName"
label="{data.eventName}"
top="0" left="0" right="0" bottom="0"
skinClass="skins.SatelliteEventSkin"
selected="{data.selected}"
click="{data.selected = !data.selected}"/>
<s:VGroup includeInLayout="{eventName.selected}"
visible="{eventName.selected}"
top="30" left="10" right="10" bottom="10">
<s:HGroup verticalAlign="middle" width="100%" >
<s:Spacer width="100%"/>
<s:Label text="eventID"/>
<s:Label id="eventID"
width="150"
text="{data.eventID}"/>
</s:HGroup>
etc...
Try to set selectedIndex value or just scroll your List using verticalScrollPosition value -myList.layout.verticalScrollPosition += your_item_height;.

Strange behaviour of scrolling in flex mobile

working on flex mobile list. list is represented using itemrenderer.
here is the itemrendeerer..
<s:Image id="img" x="30" y="50"/>
<s:Label id="nameLbl" width="100%" height="100%" text="Label" textAlign="center" verticalAlign="middle"/>
<s:Button id="checkMarkLabel" label="+" height="100%" />
on selected::
protected function onClicked(event:MouseEvent):void
{
if(checkMarkLabel.label =="✓")
{
checkMarkLabel.label = "+";
}
else if(checkMarkLabel.label == "+" )
{
checkMarkLabel.label = "✓";
trace("id::"+event.currentTarget.data.id)
//FlexGlobals.topLevelApplication.selectedId = event.currentTarget.data.id;
}
}
the image gives you the clear picture.
after selecting some items in the list,if i scroll the list,the checked items gets unchecked and the unchecked items gets checked.any answer is appreciable..
Flex don't create renderer for each item in list instead Flex create few renderers (in your case 6) and reuse them.
You must save data about clicked list items (maybe use some singleton), and then you must override set data method in renderer class (in this method you get list item for renderer), then you figure out clicked this item or not and set to checkMarkLabel corresponded symbol.
On the list you can set the property "useVirtualLayout" to false. This will generate an unique itemrenderer for each item in the list. This is also what Anton was talking about.
This is however less resource friendly. If your list get's really large it will take up more memory.
You should work with states that are already made use of by lists in combination with itemrenderers.
Example itemrenderer:
<fx:Script>
<![CDATA[
protected function marker_clickHandler(event:MouseEvent):void {
marker.label = marker.label == "V" ? "+" : "V";
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="selected"/>
</s:states>
<s:Button label.selected="V" label.normal="+"/>
<s:Button y="10" id="marker" click="marker_clickHandler(event)" label="+"/>
If you were to use this as an itemrenderer, the button utilizing states will update as expected, but like Anton mentioned, the ones marked manually onClick will not get updated as expected.
This answer builds on Robin van den Bogaard's answer.
Assuming your current dataProvider has objects that look like this:
public class MyData {
[Bindable]
private var imgUrl:String;
[Bindable]
private var name:String;
}
Add a new field to it:
[Bindable]
private var chosen:Boolean;
(If you don't have [Bindable], add it to enable data binding on the data items.)
Then your itemRenderer can look like this, automatically updating as you scroll:
<fx:Script>
<![CDATA[
protected function marker_clickHandler(event:MouseEvent):void {
data.chosen = !data.chosen;
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="selected"/>
</s:states>
<s:Image id="img" x="30" y="50" source="{data.imgUrl}" />
<s:Label id="nameLbl" width="100%" height="100%" text="Label" textAlign="center" verticalAlign="middle" text="{data.name}" />
<s:Button id="checkMarkLabel" label="{data.chosen ? '✓' : '+'}" height="100%" click="marker_clickHandler(event)" />

TextInput as ItemEditor in spark datagrid where the third column values should not duplicate

My datagrid has 3 columns and the third column is having the textinput itemEditor. when the text changes and if that text matches with any other text(basically the text is an int). the popUp should appear as duplicate. here is the code what i wrote which actually not working properly and I'm new to the flex, so please don't mind if my code is weird.
<s:GridItemEditor xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
override public function set data(value:Object):void
{
super.data = value;
col3TextField.text = data.columnThree;
}
/*
override public function set value(newValue:Object):void {
col3TextField.text = newValue as String;
}
*/
override public function get value():Object {
if (parseInt(col3TextField.text) == data.columnThree) {
return data[column.dataField];
}
return col3TextField.text;
}
override public function save():Boolean
{
if (parseInt(col3TextField.text) == data.columnThree) {
Alert.show("Duplicate");
}
}
data[column.dataField] = value;
return true;
}
]]>
</fx:Script>
<s:TextInput id="col3TextField" width="100%" color="red" restrict="0-9" maxChars="4"/>
</s:GridItemEditor>
<s:DataGrid x="139" y="340" width="300" height="300" dataProvider="{dgData}" editable="true"
>
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="columnOne" headerText="Data Col #1" editable="false"/>
<s:GridColumn dataField="columnTwo" headerText="Data Col #2" editable="false"/>
<s:GridColumn dataField="columnThree" headerText="Data Col #3" itemEditor="custom.CustomItemEditor" >
</s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
Instead of dispatching the alert from inside the ItemRenderer, dispatch a custom event with an ID like "ItemSaveEvent" and handle your business logic either where the datagrid lives, or even better, in a presentation model.
That said, be careful with your equality check. parseInt returns a Number type. Is your data.columnthree a Number? If so, then make sure you want value equality:
See this stackOverflow post that hints on custom events in itemRenderers.

filter rows by specifying the number in data grid using flex 4.5

I'm using flex builder 4.5. A data grid displays 20 rows. I want to display the specified number of rows in data grid header. Is it possible to do? Can anyone advise on this?
This can be done by Binding a String to headerText property of grid column.
its look like
<fx:Script>
<![CDATA[
[Bindable]
private var _personString:String = "";
/*change this variable's value will change the value of Header Named
"fullNameColumn".if you want to make some default value then assign
some default value to this _perosnString varialbe.*/
]]>
</fx:Script>
<s:DataGrid id="personsDataGrid"
width="100%"
height="100%"
selectedIndex="0">
<s:columns>
<s:ArrayList>
<s:GridColumn id="fullNameColumn"
dataField="YOUR_FNAME_DATAFIELD"
headerText="{ _personString.toUpperCase() } NAME"
minWidth="100"
maxWidth="250" />
<s:GridColumn headerText="PHONE"
dataField="YOUR_EMAIL_DATAFIELD"
minWidth="150"
maxWidth="250" />
<s:GridColumn headerText="EMAIL"
dataField="YOUR_EMAIL_DATAFIELD"
minWidth="150"
maxWidth="250" />
</s:ArrayList>
</s:columns>
</s:DataGrid>
May this will help you!!!