Flex Spark DataGrid GridItemEditorSessionSave Event issue - apache-flex

I have a strange problem in Flex s:DataGrid/>. The gridItemEditorSessionSave event triggers two times for me. The minimum code to recreate this issue is below:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication 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>
<s:ArrayCollection id="dp">
<fx:Object test="Test"/>
</s:ArrayCollection>
</fx:Declarations>
<fx:Script>
<![CDATA[
import spark.events.GridItemEditorEvent;
protected function onGridItemEditorSessionSave(event:GridItemEditorEvent):void
{
trace("Edited >>>", event.columnIndex);
}
protected function onGridItemEditorSessionStart(event:GridItemEditorEvent):void
{
trace("Edit Start >>>", event.columnIndex);
}
]]>
</fx:Script>
<s:DataGrid dataProvider="{dp}" width="100%" height="100%" editable="true"
gridItemEditorSessionSave="onGridItemEditorSessionSave(event)"
gridItemEditorSessionStart="onGridItemEditorSessionStart(event)">
<s:columns>
<s:ArrayCollection>
<s:GridColumn dataField="test"/>
</s:ArrayCollection>
</s:columns>
</s:DataGrid>
</s:WindowedApplication>
When I edit the cell, the trace statement is as below :
Edit Start >>> 0
Edited >>> 0
Edited >>> 0
Which indicates onGridItemEditorSessionSave triggers twice! Not sure I am missing anything.
Any help appreciated, thanks in advance!

Yes, it seems like a bug. There are other reports for this : http://apache-flex-users.2333346.n4.nabble.com/spark-Datagrid-GridItemEditorEvent-firing-twice-td3582.html
As mentioned in this discussion I have done a workaround by setting a flag _goForCellEdit=true in the ItemListEditStart event and checked this in gridItemEditorSessionSave event. Hope will help if some one ran into the same problem.

Related

Flex datagrid header row right click

I got a Datagrid in my Flex application.
I need to make appear a context menu when the header row is right-clicked.
The latter context menu must not appear when the rest of the datagrid items (the ones containing data) are clicked.
Edit: the application runs in AIR environment, so i got no flash-player troubles
In flex, and more generally in flash, there is no way to catch the the right click event.
I'm not sure about the right mouse click, cos flex apps run in flash player, and right click brings up its menu.
The best bet would be to use headerRelease event on your DatagRid. In your event handler you can then create your menu (maybe in a popup or some hovering panel?) and then do what you need to do there.
Read more about it here
edit:
Maybe you could use a contextMenu class, and attach it to your dataGrid.contextMenu?
Below code may help you: -
I have created sample in which i have added only one ITEM. You can convert it and change logic as per requirement. My idea is to provide one of the base logic. You may gey better solution but this can work for you.
<?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" minWidth="955" minHeight="600"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:DataGrid id="myDG" width="350">
<mx:dataProvider>
<mx:ArrayCollection>
<mx:source>
<fx:Object Artist="" Price="11.99"
Album="Slanted and Enchanted" />
<fx:Object Artist=""
Album="Brighten the Corners" Price="11.99" />
</mx:source>
</mx:ArrayCollection>
</mx:dataProvider>
<mx:columns>
<mx:DataGridColumn dataField="Artist" headerRenderer="StackLabelRenderer"/>
<mx:DataGridColumn dataField="Album" headerRenderer="StackLabelRenderer"/>
<mx:DataGridColumn id="price" dataField="Price" headerRenderer="StackLabelRenderer"/>
</mx:columns>
</mx:DataGrid>
</s:Application>
StackLabelRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Label xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
click="dispatchClickEvent()">
<fx:Script>
<![CDATA[
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.controls.dataGridClasses.DataGridListData;
import mx.core.mx_internal;
private function dispatchClickEvent():void
{
trace("Item Clicked")
}
import mx.controls.Alert;
[Bindable]
private var cm:ContextMenu;
override protected function createChildren():void
{
cm = new ContextMenu();
cm.hideBuiltInItems();
cm.addEventListener(ContextMenuEvent.MENU_SELECT, contextMenu_menuSelect);
this.contextMenu = cm;
}
private function contextMenu_menuSelect(evt:ContextMenuEvent):void {
//condition to check length of column data length
var allNull:Boolean=true;
var columnName:String = DataGridColumn(data).headerText;
for each(var o:Object in DataGrid(owner).dataProvider) {
if(o[columnName] != "") {
allNull=false;
break;
}
}
if(!allNull)
{
var cmi:ContextMenuItem = new ContextMenuItem("First Element...", true);
cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, contextMenuItem_menuItemSelect);
cm.customItems = [cmi];
}
}
private function contextMenuItem_menuItemSelect(evt:ContextMenuEvent):void {
}
]]>
</fx:Script>
</mx:Label>

How to get the value of a ComboBox in ActionScript

I want to show the value of a ComboBox in it's Change event handler. The labelField is assigned dynamically, so that I don't know what it is when I run the event handler
cmbArea.labelField = qry.outFields[0];
I was hoping that I can have access to the value of selectedItem like:
protected function cmbArea_changeHandler(event:IndexChangeEvent):void{
// TODO Auto-generated method stub
Alert.show(event.target.selectedItem.value);
}
But it didn't work.
Any help would be much appreciated.
It's difficult to debug this without seeing your data provider code or the error message. However, it doesn't matter that the labelField is assigned dynamically. What you have will work if elements in your data provider have a property named "value". If the only property in your data provider is the one you assign as the labelField, you should be able to access it in your change handler with the following:
Alert.show(ComboBox(event.target).selectedItem);
<?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:Script>
<![CDATA[
import mx.controls.Alert;
import spark.events.IndexChangeEvent;
protected function comboBox_changeHandler(event:IndexChangeEvent):void
{
Alert.show(comboBox.selectedItem);
}
]]>
</fx:Script>
<s:ComboBox id="comboBox"
change="comboBox_changeHandler(event)">
<s:dataProvider>
<s:ArrayList>
<fx:String>Item 1</fx:String>
<fx:String>Item 2</fx:String>
<fx:String>Item 3</fx:String>
</s:ArrayList>
</s:dataProvider>
</s:ComboBox>
</s:Application>
I tested the following line and seems it works:
Alert.show(event.target.selectedItem[event.target.labelField]);

Flex Spark List component item order

I have a regular spark list which is sorted correctly when no item renderer is used. However, when the following item renderer is used, the list shuffles and displays items from previous instances of the list. Any help would be appreciated.
<?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"
creationComplete="itemRendererInit(event)">
<fx:Script>
<![CDATA[
import flash.utils.setInterval;
import flashx.textLayout.conversion.TextConverter;
import mx.events.FlexEvent;
protected function itemRendererInit(event:FlexEvent):void {
setInterval(resizeItemRenderer, 50);
richtext.textFlow= TextConverter.importToFlow(
'<TextFlow xmlns="http://ns.adobe.com/textLayout/2008"><linkNormalFormat color="#ac0000" textDecoration="none"/><linkHoverFormat color="#ac0000" textDecoration="underline"/><linkActiveFormat color="#ac0000" textDecoration="none"/><p><span fontWeight="bold">' +
data[0].toString() +
':</span><br/><br/>' +
data[1].toString() +
'</p></TextFlow>', TextConverter.TEXT_LAYOUT_FORMAT);
}
private function resizeItemRenderer():void {
richtext.width = parentApplication.width-525;
}
]]>
</fx:Script>
<s:RichEditableText id="richtext"
paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"
verticalAlign="middle" editable="false" textAlign="left"/>
</s:ItemRenderer>
Just over the top of my head, try overriding commitProperties instead of relying on creationComplete event. On creationComplete, just call invalidateProperties and then call your function from commitProperties().
I eventually found it to be a data binding problem. Thanks #M.D.

stopEventPropagation beyond current component

I have a TextInput inside a spark Item Renderer. I need to undo some behavior in a library I'm using by stopPropagation of the mouseDown and mouseUp event for the TextInput. However, I would like the TextInput itself to handle such events normally - otherwise the caret to cursor transitions don't seem to be properly handled. I'm ashamed to admit, I'm not sure how to do this - seems simple but I have been stuck on it for some time.
thank you!
Edit: ok, here's some code to explain what's going on (although it's completely unrelated from what I'm doing, so it's not an exact depiction of my specific situation). As I mentioned above I need to be able to stop the propagation of mouseDown and mouseUp from the TextInput to a component up the food chain - event.stopPropagation() in mouseDown and mouseUp for the TextInput does the trick. However, it messes up the caret / cursor handling for the TextInput itself. Try the code below with or without the event.stopPropagation() and you should see what I mean.
Main
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2009/03/19/using-a-custom-item-renderer-function-with-the-fxlist-control-in-flex-gumbo/ -->
<s:Application name="Spark_List_itemRendererFunction_test"
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:Script>
<![CDATA[
import mx.core.ClassFactory;
import spark.skins.spark.DefaultItemRenderer;
private function list_itemRendererFunc(item:Object):ClassFactory {
var cla:Class = DefaultItemRenderer;
switch (item.type) {
case "employee":
case "manager":
cla = EmployeeItemRenderer;
break;
default:
break;
}
return new ClassFactory(cla);
}
]]>
</fx:Script>
<s:List id="list"
labelField="name"
itemRendererFunction="list_itemRendererFunc"
horizontalCenter="0" verticalCenter="0">
<s:dataProvider>
<s:ArrayList>
<fx:Object name="Employee 1" type="employee" />
<fx:Object name="Employee 2" type="employee" />
<fx:Object name="Employee 3" type="employee" />
<fx:Object name="Employee 4" type="employee" />
<fx:Object name="Manager 1" type="manager" />
<fx:Object name="Manager 2" type="manager" />
<fx:Object name="Employee 5" type="employee" />
<fx:Object name="Manager 3" type="manager" />
<fx:Object name="Consultant 1" type="consultant" />
</s:ArrayList>
</s:dataProvider>
</s:List>
</s:Application>
and EmployeeItemRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2009/03/19/using-a-custom-item-renderer-function-with-the-fxlist-control-in-flex-gumbo/ -->
<s:ItemRenderer name="EmployeeItemRenderer"
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>
<![CDATA[
protected function TI_mouseDownHandler(event:MouseEvent):void
{
event.stopPropagation();
}
protected function TI_mouseUpHandler(event:MouseEvent):void
{
event.stopPropagation();
}
]]>
</fx:Script>
<s:HGroup>
<s:Label id="labelDisplay" left="4" right="4" top="4" bottom="4" />
<s:TextInput id="TI" mouseDown="TI_mouseDownHandler(event)" mouseUp="TI_mouseUpHandler(event)"/>
</s:HGroup>
</s:ItemRenderer>
Can you post what you've tried so far?
I think all you would need to do is register listeners for the mouseDown, mouseUp, and click events and then use http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html#stopPropagation() to stop the events from bubbling further from the currentTarget out to the parents, stopImmediatePropagation would stop the event from triggering listeners on the current object.
Shaun
PS I'll edit if you post some code and I can clarify.
OK, Sounds like this is only an issue for Flex 4.01 (thank you JAX). In such case I got what I wanted by stopping propagation on the mousedown event but not on the mouseUp. This is a very specific case that applies to my code, so I'm not sure if it'll be really useful for anyone else. I guess the interesting lesson for me, here, is that mouseUp is the event that is related to caret / system cursor management.

Auto-resizing Spark TextArea using Flex Hero

I'm trying to auto-resize a Spark TextArea using Flex Hero but having no luck. Can anyone point me in the direction of a working example please?
EDIT: To clarify, I want to auto-resize the TextArea when typing, so there's never a scroll bar.
After some playing around I found a way to do it:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:VerticalLayout paddingLeft="10" paddingRight="10" paddingTop="8" paddingBottom="8"/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.core.mx_internal;
protected function changeTextArea():void
{
textArea.heightInLines = NaN;
}
protected function lineCount():void
{
label.text = textArea.textFlow.flowComposer.numLines.toString();
}
]]>
</fx:Script>
<s:TextArea id="textArea"
heightInLines="1"
horizontalCenter="0" verticalCenter="0" verticalScrollPolicy="off" horizontalScrollPolicy="off"
change="changeTextArea()" focusOut="lineCount()"/>
<s:Label id="label"/>
<s:Button/>
</s:WindowedApplication>
I just set the width/height to be a percentage of the container:
<s:TextArea width="100%" height="100%" />
Unless you are asking something else?
I just tested it with flex hero, and as Bruno Trincão posted here, s:RichEditableText works with textArea.heightInLines = NaN;

Resources