Flex DataGrid column sorting has no effect - apache-flex

I want to sort these associations in a alphabetic order.
Label Function is below from where the column is getting values.
private function setColumnLabel(item:Object, col:*):String
{
if(AssociationModel(item).service != null)
return
AssociationModel(item).service.serviceName
+"["+AssociationMoel(item).service.siServiceId+"]";
else
return "";
}
<mx:DataGrid id="subLinearAssocGridInView"
width="600"
top="30"
left="12"
editable="false"
maxHeight="500"
rowHeight="20"
headerHeight="20">
<mx:columns>
<mx:DataGridColumn [Si_Service_Id]"
headerText="Service
editable="false"
dataField="service"
labelFunction="setColumnLabel"
sortable="true"/>
</mx:columns>
</mx:DataGrid>
Here i have tried with sortabledecsending=true and sortabledecsending=true but it has no effect
<mx:DataGridColumn
headerText="Service [Si_Service_Id]"
editable="false"
dataField="service"
labelFunction="setServiceColumnLabel"
sortabledecsending=true
sortable="true"/>
And also i have tried using sortCompareFunction.
public function doSortForField(field:String):Function
{
return function(obj1:Object, obj2:Object):int
{
return mx.utils.ObjectUtil.stringCompare(obj1[field],obj2[field],true);
}
<mx:DataGrid>
<mx:columns>
<mx:DataGridColumn
sortCompareFunction=”doSortForField(‘service’)”
headerText=”service” dataField=”service” />
</mx:columns>
</mx:DataGrid>
But this has also no effect.
please suggest where i am missing . Thanks in advance.

You were almost right, just one thing you've missed to add:
public function doSortForField(field:String, property:String):Function
{
return function (obj1:Object, obj2:Object):int
{
return mx.utils.ObjectUtil.stringCompare(obj1[field][property], obj2[field][property], true);
}
}
But still it won't be sorted by default - you'll have to click on column header to sort it dec/acc. See resulted code below:
<?xml version="1.0"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="creationCompleteHandler(event)">
<mx:DataGrid id="subLinearAssocGridInView"
width="600"
top="30"
left="12"
editable="false"
maxHeight="500"
rowHeight="20"
headerHeight="20"
sortableColumns="true"
>
<mx:columns>
<mx:DataGridColumn
headerText="Service"
editable="false"
dataField="service"
labelFunction="setColumnLabel"
sortCompareFunction="doSortForField('service', 'serviceName')"
/>
</mx:columns>
</mx:DataGrid>
<fx:Script><![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
import mx.utils.ObjectUtil;
private function creationCompleteHandler(event:FlexEvent):void
{
const mockData:ArrayCollection = new ArrayCollection([
{service: {serviceName: "service1", siServiceId: "serviceId1"}},
{service: {serviceName: "service2", siServiceId: "serviceId2"}},
{service: {serviceName: "service3", siServiceId: "serviceId3"}},
{service: {serviceName: "service4", siServiceId: "serviceId4"}}
]);
subLinearAssocGridInView.dataProvider = mockData;
}
private function setColumnLabel(item:Object, col:*):String
{
if (item.service != null)
{
return item.service.serviceName + "[" + item.service.siServiceId + "]";
}
else
{
return "";
}
}
public function doSortForField(field:String, property:String):Function
{
return function (obj1:Object, obj2:Object):int
{
return mx.utils.ObjectUtil.stringCompare(obj1[field][property], obj2[field][property], true);
}
}
]]></fx:Script>
In case you want to apply default sorting:
private function subLinearAssocGridInView_creationCompleteHandler(event:FlexEvent):void
{
mockData.sort = new Sort();
mockData.sort.fields = [
new SortField('serviceName', true, true, false, null, doSortForField('service', 'serviceName'))
];
mockData.refresh();
}
So the resulted code will be:
<?xml version="1.0"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx">
<mx:DataGrid id="subLinearAssocGridInView"
dataProvider="{mockData}"
width="600"
top="30"
left="12"
editable="false"
maxHeight="500"
rowHeight="20"
headerHeight="20"
creationComplete="subLinearAssocGridInView_creationCompleteHandler(event)"
>
<mx:columns>
<mx:DataGridColumn
headerText="Service"
editable="false"
labelFunction="setColumnLabel"
sortCompareFunction="doSortForField()"
/>
</mx:columns>
</mx:DataGrid>
<fx:Script><![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.Sort;
import mx.collections.SortField;
import mx.events.FlexEvent;
import mx.utils.ObjectUtil;
private static const SERVICE_FIELD:String = 'service';
private static const SERVICE_NAME_PROPERTY:String = 'serviceName';
[Bindable]
public var mockData:ArrayCollection = new ArrayCollection([
{service: {serviceName: "service1", siServiceId: "serviceId1"}},
{service: {serviceName: "service2", siServiceId: "serviceId2"}},
{service: {serviceName: "service3", siServiceId: "serviceId3"}},
{service: {serviceName: "service4", siServiceId: "serviceId4"}}
]);
private function setColumnLabel(item:Object, col:*):String
{
if (item.service != null)
{
return item.service.serviceName + "[" + item.service.siServiceId + "]";
}
else
{
return "";
}
}
public function doSortForField(field:String = SERVICE_FIELD, property:String = SERVICE_NAME_PROPERTY):Function
{
return function (obj1:Object, obj2:Object):int
{
return mx.utils.ObjectUtil.stringCompare(obj1[field][property], obj2[field][property], true);
}
}
private function subLinearAssocGridInView_creationCompleteHandler(event:FlexEvent):void
{
mockData.sort = new Sort();
mockData.sort.fields = [
new SortField(SERVICE_NAME_PROPERTY, true, true, false, null, doSortForField())
];
mockData.refresh();
}
]]></fx:Script>

Have you tried sorting the dataProvider content instead? If you are using Array then use Array.sort(). If you are using ArrayCollection then use its sort field

Related

Combobox NoClose when embedded Checkbox is clicked [FLEX]

I've reached the point where I have got a dropdown in which is embedded a tree. Each node has got a checkbox.
The idea is to be able to navigate and tick the checkboxes without having the dropdown closing.
Can't make this dropdown to remain open after a checkbox has been clicked!
The event that closes the dropdown occurs when the xml is updated in PermissionTreeItemRendererV2.as > handleChkClick(evt) > this.itemXml.#checked = {"0" or "1"};
Any idea how to tweak the code to disable this annoying event?
sample_combobox.mxml:
<?xml version="1.0"?>
<mx:Application xmlns:local="local.*"
xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="loadXML()">
<mx:Script>
<![CDATA[
import mx.collections.XMLListCollection;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.mxml.HTTPService;
public var xmlService:HTTPService = new HTTPService();
[Bindable]
public var xmlResult:XML;
[Bindable]
public var xmlList:XMLList;
[Bindable]
public var xmlTeams:XMLListCollection;
public function loadXML():void
{
xmlService.url = "mlb.xml"
xmlService.resultFormat = "e4x";
xmlService.addEventListener(ResultEvent.RESULT, resultHandler);
xmlService.send();
}
public function resultHandler(event:ResultEvent):void
{
xmlResult = XML(event.result);
xmlList = xmlResult.league;
xmlTeams = new XMLListCollection(xmlList);
}
]]>
</mx:Script>
<local:TreeComboBox
width="300"
id="combo"
labelField="#label" dataProvider="{xmlTeams}" />
</mx:Application>
TreeCombobox.mxml:
<?xml version="1.0" encoding="utf-8"?>
<local:ComboBoxNoClose xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:local="local.*">
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
[Bindable]
private var _label:String;
[Bindable]
public var treeSelectedItem:Object;
public function updateLabel(event:*):void
{
_label = event.currentTarget.selectedItem[this.labelField];
treeSelectedItem = event.currentTarget.selectedItem;
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(dropdown && _label != null){
text = "";//_label;
}
}
]]>
</mx:Script>
<local:dropdownFactory>
<mx:Component>
<mx:Tree change="outerDocument.updateLabel(event)" height="500"
width="500"
itemRenderer="local.PermissionsTreeItemRendererV2"
folderClosedIcon="{null}"
folderOpenIcon="{null}"
defaultLeafIcon="{null}" />
</mx:Component>
</local:dropdownFactory>
</local:ComboBoxNoClose>
PermissionTreeItemRendererV2.as
// ActionScript file
package local
{
import flash.events.Event;
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.collections.ArrayList;
import mx.collections.ListCollectionView;
import mx.controls.CheckBox;
import mx.controls.treeClasses.TreeItemRenderer;
import mx.controls.treeClasses.TreeListData;
public class PermissionsTreeItemRendererV2 extends TreeItemRenderer{
public var chk:CheckBox;
public var itemXml:XML;
public function PermissionsTreeItemRendererV2(){
super();
mouseEnabled = false;
}
override public function set data(value:Object):void{
if(value != null){
super.data = value;
this.itemXml = XML(value);
if(this.itemXml.#checked == "1"){
this.chk.selected = true;
}else{
this.chk.selected = false;
}
}
}
override protected function createChildren():void{
super.createChildren();
chk = new CheckBox();
chk.addEventListener(MouseEvent.CLICK, handleChkClick);
addChild(chk);
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth,unscaledHeight);
if(super.data){
var tld:TreeListData = TreeListData(super.listData);
//In some cases you only want a checkbox to appear if an
//item is a leaf
//if so, then keep the following block uncommented,
//otherwise you can comment it out to display the checkbox
//for branch nodes
if(tld.hasChildren){
this.chk.visible = true;
}else{
//You HAVE to have the else case to set visible to true
//even though you'd think the default would be visible
//it's an issue with itemrenderers...
this.chk.visible = true;
}
if(chk.visible){
//if the checkbox is visible then
//reposition the controls to make room for checkbox
this.chk.x = super.label.x
super.label.x = this.chk.x + 17;
this.chk.y = super.label.y+8;
}
}
}
private function handleChkClick(evt:MouseEvent):void
{
if(this.chk.selected)
{
this.itemXml.#checked = "1";
}
else
{
this.itemXml.#checked = "0";
}
}
}
}
ComboboxNoClose.as:
package local
{
import flash.events.Event;
import flash.events.MouseEvent;
import mx.controls.CheckBox;
import mx.controls.ComboBox;
import mx.events.DropdownEvent;
import mx.events.ListEvent;
public class ComboBoxNoClose extends ComboBox
{
public function ComboBoxNoClose()
{
super();
}
public function onOpen(event:Event):void
{
event.stopImmediatePropagation();
}
public override function close(trigger:Event = null):void
{
if (trigger != null)
{
super.close();
}
}
}
}
mlb.xml that populates the tree:
<?xml version="1.0" encoding="utf-8"?>
<root>
<league label="American League">
<division label="West">
<team label="Los Angeles" />
<team label="Seattle" />
<team label="Oakland" />
<team label="Texas" />
</division>
<division label="Central">
<team label="Cleveland" />
<team label="Detroit" />
<team label="Minnesota" />
<team label="Chicago" />
<team label="Kansas City" />
</division>
<division label="East">
<team label="Boston" />
<team label="New York" />
<team label="Toronto" />
<team label="Baltimore" />
<team label="Tampa Bay" />
</division>
</league>
</root>
Default behavior of popup is that, when you click on dropdown it closes it self. You can solve this problem like this
<mx:PopUpButton id="popup" width="100%" label="{label}" close="popup_closeHandler(event)" open="popup_openHandler(event)" openAlways="true">
<mx:popUp>
<mx:VBox width="{popup.width*1.25}" mouseEnabled="false" verticalGap="1">
<mx:List id="listSelectAll" width="100%" rowCount="1" selectable="true" itemClick="listSelectAll_itemClickHandler(event)">
<mx:dataProvider>
<mx:Array>
<mx:Object id="selectAll" selected="" label="All"/>
</mx:Array>
</mx:dataProvider>
<mx:itemRenderer>
<mx:Component>
<mx:HBox width="100%" height="100%" mouseChildren="false">
<mx:CheckBox selected="{data.selected}" label="{data.label}" width="100%"/>
</mx:HBox>
</mx:Component>
</mx:itemRenderer>
</mx:List>
<mx:List id="listItems" width="100%" dataProvider="{_dataProvider}" itemClick="listItems_itemClickHandler(event)" variableRowHeight="true">
<mx:itemRenderer>
<mx:Component>
<!--
<mx:HBox width="100%" height="100%" mouseChildren="false" verticalAlign="middle">
<mx:CheckBox selected="{data[outerDocument.selectedField]}" label="{data[outerDocument.labelField]}" width="100%"/>
</mx:HBox>
-->
<mx:HBox width="100%" mouseChildren="false" verticalAlign="middle" horizontalAlign="left" paddingLeft="4">
<mx:Script>
<![CDATA[
override public function set data(value: Object) : void {
super.data = value;
if(data.iconCache == null || outerDocument.cacheIcon == false) {
imgIcon.source = data[outerDocument.iconField];
} else {
imgIcon.source = new Bitmap(data.iconCache);
}
}
protected function image_ioErrorHandler(event:IOErrorEvent):void {
imgIcon.visible = imgIcon.includeInLayout = false;
}
protected function imgIcon_completeHandler(event:Event):void {
imgIcon.visible = imgIcon.includeInLayout = true;
if(outerDocument.cacheIcon) {
var bitmapData:BitmapData = Bitmap(imgIcon.content).bitmapData;
//var bitmap:Bitmap = new Bitmap(bitmapData);
data.iconCache = bitmapData;
//imgIcon.removeEventListener(Event.COMPLETE, imgIcon_completeHandler);
}
}
]]>
</mx:Script>
<mx:CheckBox id="chkSelected" selected="{data[outerDocument.selectedField]}"/>
<mx:Image id="imgIcon" width="{outerDocument.iconWidth}" height="{outerDocument.iconHeight}" visible="{data[outerDocument.iconField]}" includeInLayout="{data[outerDocument.iconField]}" complete="imgIcon_completeHandler(event)" ioError="image_ioErrorHandler(event)"/>
<mx:Label id="lblText" text="{data[outerDocument.labelField]}"/>
</mx:HBox>
</mx:Component>
</mx:itemRenderer>
</mx:List>
</mx:VBox>
</mx:popUp>
</mx:PopUpButton>
or you can visit my post for a complete implementation. here

How to add a Image to the ToolTip?

I want to add a image to the tooTip that i have have currently. So that when u rollover the row its show a the ship information and a image of a ship. I want the image to be displayed according to the type of ship. There is mainly 3 type. So according to the type i will display the image and the text information about the ship. For now I just used dummy data.I dont know if the toolTip can support to hold an image.
So my Ouestions:
How to add an image to the existing tool tip i have(in the yellow box)
how to add the image in away which is not really static so that I can display according to ship type later on.
Pls can someone help me with this.
Thank you soo much :)
This is the code I currently have (Its the entire codes so u can run on ur pc if u want) :
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import spark.events.GridEvent;
import spark.components.Image;
[Bindable]
private var myArrivalShips:ArrayCollection = new ArrayCollection([
{arrivalShipsName:"Ship A", ETD:"12 March"},
{arrivalShipsName:"Ship B", ETD:"25 March"}
]);
private function buildToolTip(item:Object,column:GridColumn):String{
var myString:String = "";
if(item != null)
{
myString = myString +"Ship name : " + item.arrivalShipsName + "\n";
myString = myString + "ETD : " + item.ETD + "\n" +"Service: Repair"+"\n"+"Length of ship : 50"+"\n"+"Agent contact: 982392398";
}
return myString;
}
]]>
</fx:Script>
<s:BorderContainer x="267" y="11" width="331" height="586">
<s:DataGrid id="arrivalTable" x="10" y="326" width="302" height="205" requestedRowCount="4" dataProvider="{myArrivalShips}" showDataTips="true" dataTipFunction="buildToolTip">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="arrivalShipsName" headerText="Arrival Ships"></s:GridColumn>
<s:GridColumn dataField="ETD" headerText="ETD"></s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
<s:BorderContainer x="10" y="19" width="302" height="285">
</s:BorderContainer>
</s:BorderContainer>
You have 2 case:
Replace ToolTipManagerImpl with own modified ToolTipManagerImpl, where you switch toolTipClass with own custom layout and skin. You can find examples.
Create custom tooltip, extends UIComponent implements IToolTip. Prototype look like original tooltip:
Main application mxml:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="creationCompleteHandler(event)"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
import mx.events.ToolTipEvent;
import mx.managers.ToolTipManager;
[Bindable]
private var myArrivalShips:ArrayCollection = new ArrayCollection([
{arrivalShipsName:"Ship A", ETD:"12 March", image: "http://url"},
{arrivalShipsName:"Ship B", ETD:"25 March", image: "http://url"}
]);
private function buildToolTip(item:Object,column:GridColumn):String
{
return JSON.stringify(item);
}
protected function creationCompleteHandler(event:FlexEvent):void
{
ToolTipManager.toolTipClass = ToolTipCustomClass;
}
]]>
</fx:Script>
<fx:Declarations></fx:Declarations>
<s:BorderContainer x="267" y="11" width="331" height="586">
<s:DataGrid id="arrivalTable" x="10" y="326" width="302" height="205" requestedRowCount="4" dataProvider="{myArrivalShips}"
showDataTips="true" dataTipFunction="buildToolTip">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="arrivalShipsName" headerText="Arrival Ships"></s:GridColumn>
<s:GridColumn dataField="ETD" headerText="ETD"></s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
<s:BorderContainer x="10" y="19" width="302" height="285">
</s:BorderContainer>
</s:BorderContainer></s:Application>
and class ToolTipCustomClass:
package
{
import flash.display.DisplayObject;
import flash.events.Event;
import mx.controls.Image;
import mx.controls.ToolTip;
import mx.core.EdgeMetrics;
import mx.core.IRectangularBorder;
import mx.core.mx_internal;
import mx.styles.ISimpleStyleClient;
import mx.utils.ObjectUtil;
use namespace mx_internal;
public class ToolTipCustomClass extends ToolTip
{
private var _image:Image;
public function ToolTipCustomClass()
{
super();
}
override protected function createChildren():void
{
mx_internal::createTextField(-1);
createBorder();
textField.visible = false;
_image = new Image();
_image.mouseChildren = false;
_image.mouseEnabled = false;
_image.addEventListener(Event.COMPLETE, onLoadCompliteHandler);
addChild(_image);
}
protected function onLoadCompliteHandler(event:Event):void
{
_image.removeEventListener(Event.COMPLETE, onLoadCompliteHandler);
textField.x = _image.contentWidth;
textField.width = textField.width - _image.width;
invalidateDisplayList();
}
override protected function measure():void
{
super.measure();
_image.width = 100;
_image.height = 100;
}
override public function set text(value:String):void
{
if (!value) return;
var str:String = "";
var item:Object;
try
{
item = JSON.parse(value);
} catch (e:Error) {}
if (item != null)
{
str += "Ship name : " + item.arrivalShipsName + "\n" +
"ETD : " + item.ETD + "\n" +
"Service: Repair\n" +
"Length of ship : 50\n" +
"Agent contact: 982392398";
_image.source = item.image;
}
super.text = str;
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
if (_image && _image.content)
{
var bm:EdgeMetrics = borderMetrics;
var leftInset:Number = bm.left + getStyle("paddingLeft");
var topInset:Number = bm.top + getStyle("paddingTop");
var rightInset:Number = bm.right + getStyle("paddingRight");
var bottomInset:Number = bm.bottom + getStyle("paddingBottom");
var widthSlop:Number = leftInset + rightInset;
var heightSlop:Number = topInset + bottomInset;
_image.move( leftInset, topInset );
border.setActualSize(unscaledWidth + _image.contentWidth, Math.max(unscaledHeight, _image.contentHeight));
textField.move(_image.contentWidth, topInset);
textField.setActualSize(unscaledWidth - widthSlop - _image.contentWidth, unscaledHeight - heightSlop);
textField.visible = true;
}
}
private function createBorder():void
{
if (!border)
{
var borderClass:Class = getStyle("borderSkin");
if (borderClass != null)
{
border = new borderClass();
if (border is ISimpleStyleClient)
ISimpleStyleClient(border).styleName = this;
addChildAt(DisplayObject(border), 0);
invalidateDisplayList();
}
}
}
private function get borderMetrics():EdgeMetrics
{
if (border is IRectangularBorder)
return IRectangularBorder(border).borderMetrics;
return EdgeMetrics.EMPTY;
}
}
}
Don't forget replace image url in items object.

Change the visibility of itemRemderer

I have and add button (last row) in one column of the AdvancedDataGrid.
for the row having the add button the rest of fields are not visible.
On click of the add button a new row is added to the grid for the user to add.
After that this button becomes delete button (label becomes '-' and a new row is added at the bottom for adding another row).
When i click on the delete button (label '-'), the last row gets the add button('+' label) but the fields of the row become visible.
Can somebody please explain
Below is the sample code
<?xml version="1.0" encoding="utf-8"?>
<s:Group 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"
initialize="group1_initializeHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.AdvancedDataGridEvent;
import mx.events.CollectionEvent;
import mx.events.DataGridEvent;
import mx.events.FlexEvent;
import mx.events.IndexChangedEvent;
import spark.events.IndexChangeEvent;
protected function group1_initializeHandler(event:FlexEvent):void
{
alarms=new ArrayCollection();
alarms.addItem(initalarmRow());
//alarms.addEventListener(CollectionEvent.COLLECTION_CHANGE, populateFieldDetails);
alarms.addItem(populateFieldforButton());
populateEvents();
}
private var _addButton:Boolean
[Bindable]
public function get addButton():Boolean
{
return _addButton;
}
public function set addButton(value:Boolean):void
{
_addButton=value;
}
private var _alarms:ArrayCollection;
[Bindable]
public function get alarms():ArrayCollection
{
return _alarms;
}
public function set alarms(value:ArrayCollection):void
{
_alarms=value;
}
private var _alarmRow:alarmVO;
[Bindable]
public function get alarmRow():alarmVO
{
return _alarmRow;
}
public function set alarmRow(value:alarmVO):void
{
_alarmRow=value;
}
// Initiliaze an alarmVO for a new row
private function initalarmRow():alarmVO
{
alarmRow=new alarmVO();
alarmRow.buttonLabel='-';
channels=new ArrayCollection;
for (var i:int=0; i < 10; i++)
{
var vo:ChannelVO=new ChannelVO();
vo.id=i;
vo.name="channel_" + i;
vo.messageType="Message_" + i;
channels.addItem(vo);
}
alarmRow.eventName="Event_1";
alarmRow.channel=channels.getItemAt(5) as ChannelVO;
return alarmRow;
}
private var _events:ArrayCollection;
[Bindable]
public function get events():ArrayCollection
{
return _events;
}
public function set events(value:ArrayCollection):void
{
_events=value;
}
private var _channels:ArrayCollection;
[Bindable]
public function get channels():ArrayCollection
{
return _channels;
}
public function set channels(value:ArrayCollection):void
{
_channels=value;
}
public function populateFieldforButton():alarmVO
{
alarmRow=new alarmVO();
alarmRow.buttonLabel="+";
return alarmRow;
}
public function populateEvents():void
{
events=new ArrayCollection();
for (var i:int=0; i < 3; i++)
{
var event:EventVO=new EventVO();
event.id=i;
event.eventName="Event_" + i;
events.addItem(event);
}
}
public function populateFieldDetails(event:Event):void
{
for (var count:int; count < alarms.length; count++)
{
//trace('alarms.getItemAt(count).buttonLabel :' + alarms.getItemAt(count).buttonLabel);
if (alarms.getItemAt(count).buttonLabel == '+')
{
alarms.getItemAt(count).channel=null;
alarms.getItemAt(count).eventName=null;
}
adgdalarmManagement.invalidateDisplayList();
}
}
public function preventEditing(event:AdvancedDataGridEvent):void
{
//check if it is the last row(it should not be editable)
if (event.rowIndex == alarms.length - 1)
{
event.preventDefault();
//trace('**** :' + event.currentTarget);
}
}
public function adgdalarmManagement_creationCompleteHandler(event:FlexEvent):void
{
}
protected function adgdalarmManagement_dataChangeHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
}
public function ddlEventType_creationCompleteHandler(event:FlexEvent, data:Object):void
{
for (var count:int=0; count < alarms.length; count++)
{
for (var count1:int=0; count1 < events.length; count1++)
{
if (events.getItemAt(count1).eventName == alarms.getItemAt(count).eventName)
{
event.currentTarget.selectedIndex=count1;
break;
}
}
}
checkEventTypeVisible(event, data);
}
public function checkEventTypeVisible(event:FlexEvent, data:Object):void
{
if (data == '-')
{
event.currentTarget.visible=true;
}
else
{
event.currentTarget.visible=false;
}
}
public function button1_clickHandler(event:MouseEvent):void
{
if (event.currentTarget.label == '-')
{
event.currentTarget.parent.parent.parent.parent.dataProvider.removeItemAt(event.currentTarget.parent.parent.parent.parent.selectedIndex);
event.currentTarget.parent.parent.parent.parent.dataProvider.refresh();
adgdalarmManagement.validateNow();
}
else
{
var selectedIndex:int=event.currentTarget.parent.parent.parent.parent.selectedIndex;
alarmRow=new alarmVO();
alarmRow.buttonLabel='-';
alarmRow.eventName="";
alarmRow.channel=new ChannelVO();
event.currentTarget.parent.parent.parent.parent.dataProvider.removeItemAt(event.currentTarget.parent.parent.parent.parent.selectedIndex);
event.currentTarget.parent.parent.parent.parent.dataProvider.addItemAt(alarmRow, selectedIndex);
event.currentTarget.parent.parent.parent.parent.dataProvider.addItemAt(populateFieldforButton(), selectedIndex + 1);
}
}
public function ddlChannel_changeHandler(event:IndexChangeEvent):void
{
event.target.parent.data.typeDisplay=event.target.selectedItem.name;
event.target.parent.data.messageTypeDisplay=event.target.selectedItem.messageType;
}
public function ddlChannel_creationCompleteHandler(event:FlexEvent, data:Object):void
{
// TODO Auto-generated method stub
if (channels != null)
{
if (alarms != null)
for (var count:int=0; count < alarms.length; count++)
{
for (var count1:int=0; count1 < channels.length; count1++)
{
if (alarms.getItemAt(count).channel != null)
{
if (channels.getItemAt(count1).name == alarms.getItemAt(count).channel.name)
{
event.currentTarget.selectedIndex=count1;
break;
}
}
else
{
event.currentTarget.selectedIndex=0;
}
}
}
}
else
{
event.currentTarget.selectedIndex=0;
}
checkVisible(event, data);
}
public function checkVisible(event:FlexEvent, data:Object):void
{
if (data == '-')
{
event.currentTarget.visible=true;
}
else
{
event.currentTarget.visible=false;
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:VGroup paddingTop="10"
paddingBottom="10"
paddingLeft="10"
paddingRight="10"
width="100%"
height="100%"
id="vbxChannelManagement">
<!-- Added for Rounding off Corners of GRID-->
<mx:ApplicationControlBar width="100%"
cornerRadius="8"
height="100%">
<mx:AdvancedDataGrid id="adgdalarmManagement"
width="100%"
height="100%"
dataProvider="{alarms}"
dataChange="adgdalarmManagement_dataChangeHandler(event)"
creationComplete="adgdalarmManagement_creationCompleteHandler(event)">
<mx:columns>
<mx:AdvancedDataGridColumn id="adgcAdRemove"
width="30"
dataField="buttonLabel">
<mx:itemRenderer>
<fx:Component>
<s:MXAdvancedDataGridItemRenderer>
<s:Button label="{data.buttonLabel}"
width="30"
click="outerDocument.button1_clickHandler(event)"/>
</s:MXAdvancedDataGridItemRenderer>
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
<mx:AdvancedDataGridColumn id="adgcEvent"
dataField="buttonLabel"
headerText="Event">
<mx:itemRenderer>
<fx:Component>
<s:MXAdvancedDataGridItemRenderer>
<s:HGroup id="eventGroup"
visible="{(this.parent.data.buttonLabel=='-')?true:false}}">
<s:DropDownList id="ddlEventType"
dataProvider="{outerDocument.events}"
creationComplete="outerDocument.ddlEventType_creationCompleteHandler(event,data.buttonLabel)"
labelField="eventName"/>
</s:HGroup>
</s:MXAdvancedDataGridItemRenderer>
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
<mx:AdvancedDataGridColumn id="adgcChannel"
dataField="buttonLabel"
headerText="Channel">
<mx:itemRenderer>
<fx:Component>
<s:MXAdvancedDataGridItemRenderer>
<!--<s:HGroup width="100%"
id="channelField"
>-->
<s:DropDownList id="ddlChannel"
width="100%"
dataProvider="{outerDocument.channels}"
creationComplete="outerDocument.ddlChannel_creationCompleteHandler(event,data.buttonLabel)"
labelField="id"
change="outerDocument.ddlChannel_changeHandler(event)"
/>
<!--</s:HGroup>-->
</s:MXAdvancedDataGridItemRenderer>
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
<mx:AdvancedDataGridColumn id="adgcChannelType"
headerText="Type"
dataField="typeDisplay"/>
<mx:AdvancedDataGridColumn id="adgcMessageType"
headerText="Message Type"
dataField="messageTypeDisplay"/>
</mx:columns>
</mx:AdvancedDataGrid>
</mx:ApplicationControlBar>
</s:VGroup>
</s:Group>
I got it working by overriding commitproperties function and in that function checking the viisbility of the dropdown.
something like
override public function commitproperties():void{
super.commitporperties();
if(data.buttonLabel == '-')
this.visible = false;
}

how to limit the rows of datagrid in flex3?

I have a data grid consisting of 3 columns & many rows, i want to show only the first 20 rows to user. Is there any way i can show only the first 20 rows in my datagrid.After by clicking button 'next', next 20 rows should display and so on...
If you have a list as a data provider (ArrayCollection or so) you can use filterFunction to filter your list.
The sample code is here:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application initialize="init()" layout="absolute" minHeight="600" minWidth="955"
xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.utils.StringUtil;
private static const DP_LENGTH:int = 100;
private static const VISIBLE_ROWS_COUNT:int = 20;
[Bindable]
private var currentPage:int = 0;
[Bindable]
private var dataProvider:ArrayCollection;
protected function init():void
{
var dpArray:Array = [];
for (var i:int = 0; i < DP_LENGTH; i++)
{
var item:Object = { first: i, second: Math.random(), third: Math.random() };
dpArray.push(item);
}
dataProvider = new ArrayCollection(dpArray);
dataProvider.filterFunction = pagingFilterFunction;
dataProvider.refresh();
}
protected function nextPage():void
{
currentPage++;
dataProvider.refresh();
}
protected function prevPage():void
{
currentPage--;
dataProvider.refresh();
}
private function pagingFilterFunction(item:Object):Boolean
{
var start:int = currentPage * VISIBLE_ROWS_COUNT;
var end:int = start + VISIBLE_ROWS_COUNT - 1;
var index:int = dataProvider.getItemIndex(item);
return (index >= start) && (index <= end);
}
]]>
</mx:Script>
<mx:VBox horizontalAlign="center" horizontalCenter="0" verticalCenter="0">
<mx:DataGrid dataProvider="{dataProvider}">
<mx:columns>
<mx:DataGridColumn dataField="first" headerText="First" />
<mx:DataGridColumn dataField="second" headerText="Second" />
<mx:DataGridColumn dataField="third" headerText="Third" />
</mx:columns>
</mx:DataGrid>
<mx:Label
text="{StringUtil.substitute('Page {0} of {1}', currentPage + 1, Math.floor ((DP_LENGTH - 1) / VISIBLE_ROWS_COUNT) + 1)}" />
<mx:HBox>
<mx:Button click="prevPage()" enabled="{currentPage > 0}" label="Prev" />
<mx:Button click="nextPage()" enabled="{DP_LENGTH / VISIBLE_ROWS_COUNT - 1 > currentPage}" label="Next" />
</mx:HBox>
</mx:VBox>
</mx:Application>

Find out which tree item has been dropped on to in Flex

I have a mx.List and a mx.Tree. I'm trying to drag items from the list to the tree but instead of have them add to the actually tree itself I just want to find out what the dropTarget on the tree is. The dropTarget variable is always null.
protected function sparkTree_dragDropHandler(event:DragEvent):void
{
var source:* = event.dragInitiator;
var target:* = event.currentTarget;
trace("Dragged......", source.selectedItem.label);
trace("From.........", source.name);
trace("To...........", event.currentTarget.name);
trace("Target Item..", event.currentTarget.dropTarget);
}
Output:
Dragged...... itemOne
From......... _Main_Tree2
To........... _Main_Tree1
Target Item.. null
So just to clarify I'm trying to get the object that the items is being dropped onto.
As a side note using:
var source:List = event.dragInitiator as List;
var target:List = event.currentTarget as List;
resulted in null object reference error. Seems odd?
UPDATE:
(Not sure where the best place to post this is but) I think this may be the solution...
Create custom event: ItemDragEvent
package events
{
import mx.core.DragSource;
import mx.core.IUIComponent;
import mx.events.DragEvent;
public class ItemDragEvent extends DragEvent
{
public static const DRAG_DROP:String = "itemDragDrop";
public static const DRAG_ENTER:String = "itemDragEnter";
public static const DRAG_EXIT:String = "itemDragExit";
public var item:Object;
public var data:Object;
public var index:Object;
public function ItemDragEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=true, dragInitiator:IUIComponent=null, dragSource:DragSource=null, action:String=null, ctrlKey:Boolean=false, altKey:Boolean=false, shiftKey:Boolean=false)
{
super(type, bubbles, cancelable, dragInitiator, dragSource, action, ctrlKey, altKey, shiftKey);
}
}
}
Create an mx.Tree item renderer: TreeItemRenderer
<?xml version="1.0" encoding="utf-8"?>
<s:MXTreeItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
dragEnter="dragEnterHandler(event)"
dragExit="dragExitHandler(event)"
dragDrop="dragDropHandler(event)"
>
<fx:Script>
<![CDATA[
import events.ItemDragEvent;
import mx.core.IUIComponent;
import mx.events.DragEvent;
import mx.managers.DragManager;
protected function dragEnterHandler(event:DragEvent):void
{
DragManager.acceptDragDrop(event.currentTarget as IUIComponent);
var e:ItemDragEvent = new ItemDragEvent(ItemDragEvent.DRAG_ENTER, true);
e.data = data;
e.item = data;
e.index = itemIndex;
dispatchEvent(e);
trace("TreeItemRenderer, dragEnterHandler");
}
protected function dragExitHandler(event:DragEvent):void
{
var e:ItemDragEvent = new ItemDragEvent(ItemDragEvent.DRAG_EXIT, true);
e.data = data;
e.item = data;
e.index = itemIndex;
dispatchEvent(e);
trace("TreeItemRenderer, dragExitHandler");
}
protected function dragDropHandler(event:DragEvent):void
{
DragManager.acceptDragDrop(event.currentTarget as IUIComponent);
var e:ItemDragEvent = new ItemDragEvent(ItemDragEvent.DRAG_DROP, true);
e.data = data;
e.item = data;
e.index = itemIndex;
dispatchEvent(e);
trace("TreeItemRenderer, dragDropHandler");
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="hovered" />
<s:State name="selected" />
</s:states>
<s:HGroup left="0" right="0" top="0" bottom="0" verticalAlign="middle">
<s:Rect id="indentationSpacer" width="{treeListData.indent}" percentHeight="100" alpha="0">
<s:fill>
<s:SolidColor color="0xFFFFFF" />
</s:fill>
</s:Rect>
<s:Group id="disclosureGroup">
<s:BitmapImage source="{treeListData.disclosureIcon}" visible="{treeListData.hasChildren}" />
</s:Group>
<s:BitmapImage source="{treeListData.icon}" />
<s:Label id="labelField" text="{treeListData.label}" paddingTop="2"/>
</s:HGroup>
</s:MXTreeItemRenderer>
Finally the Main code
</fx:Declarations>
<fx:Script>
<![CDATA[
import events.ItemDragEvent;
import itemRenderers.TreeItemRenderer;
import mx.collections.ArrayCollection;
import mx.events.DragEvent;
import mx.events.FlexEvent;
import mx.utils.ObjectUtil;
[Bindable]
private var listData:ArrayCollection = new ArrayCollection([ "One", "Two", "Three" ]);
[Bindable]
private var treeData:Object = { label: "First", children: new ArrayCollection([ { label: "Second" }, { label: "Third" } ]) };
protected function windowedapplication1_initializeHandler(event:FlexEvent):void
{
tree1.addEventListener(ItemDragEvent.DRAG_DROP, treeItemDragDropHandler);
}
protected function treeItemDragDropHandler(event:ItemDragEvent):void
{
event.preventDefault();
trace("ItemDragDrop:", ObjectUtil.toString(event.data));
}
]]>
</fx:Script>
<s:layout>
<s:HorizontalLayout horizontalAlign="center" verticalAlign="middle" />
</s:layout>
<mx:Tree id="list1" width="50%" height="100%"
dataProvider="{listData}" labelField="label"
dragEnabled="true"
dragMoveEnabled="true"
dropEnabled="true" />
<mx:Tree id="tree1" width="50%" height="100%"
dataProvider="{treeData}"
dragEnabled="true"
dropEnabled="true"
showRoot="true"
itemRenderer="itemRenderers.TreeItemRenderer" />
Needs a bit of work to sort out visual feedback, but that should output the Tree item that was dropped onto.
In regards to
var source:List = event.dragInitiator as List;
var target:List = event.currentTarget as List;
Try to check your imports. Maybe there was imported Spark lists but you're using MX List? :)
In regards to dropTarget property please refer to documentation about it. It doesn't relate to Flex drag-n-drop functionality. And so there is no surprise the value of this property is null.
What about your problem in general you can use the following snippet which doesn't solve all the problems (I have no time to debug all the aspects) but can provide you some good starting point:
<?xml version="1.0" encoding="utf-8"?>
<s:Application minHeight="600" minWidth="955" xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.ICollectionView;
import mx.events.DragEvent;
import mx.managers.DragManager;
[Bindable]
private var listDataProvider:ArrayCollection = new ArrayCollection([ "First", "Second", "Third" ]);
[Bindable]
private var treeDataProvider:Object =
{ label: "First", children: new ArrayCollection([ { label: "Second" }, { label: "Third" } ]) };
protected function list_dragCompleteHandler(event:DragEvent):void
{
if (event.relatedObject == tree)
{
event.preventDefault();
if (event.action == DragManager.MOVE && list.dragMoveEnabled)
{
var items:Array = event.dragSource.dataForFormat("items") as Array;
var collection:ArrayCollection = list.dataProvider as ArrayCollection;
for each (var item:Object in items)
{
if (collection.contains(item))
collection.removeItemAt(collection.getItemIndex(item));
}
}
}
}
protected function tree_dragDropHandler(event:DragEvent):void
{
var source:List = List(event.dragInitiator);
var target:Tree = Tree(event.currentTarget);
trace("Dragged......", source.selectedItem);
trace("From.........", source.name);
trace("To...........", target.name);
event.preventDefault();
tree.hideDropFeedback(event);
var index:int = tree.calculateDropIndex(event);
var items:Array = new Array();
if (event.dragSource.hasFormat("treeItems"))
items = items.concat(event.dragSource.dataForFormat("treeItems") as Array);
if (event.dragSource.hasFormat("items"))
items = items.concat(event.dragSource.dataForFormat("items") as Array);
if (index > (tree.dataProvider as ICollectionView).length)
index = (tree.dataProvider as ICollectionView).length;
for each (var item:Object in items)
{
var obj:Object = new Object()
obj.label = item;
(tree.dataProvider as ArrayCollection).addItemAt(obj, index);
}
}
protected function tree_dragEnterHandler(event:DragEvent):void
{
if (event.dragInitiator == list)
{
event.preventDefault();
DragManager.acceptDragDrop(event.target as Tree);
tree.showDropFeedback(event);
}
}
protected function tree_dragExitHandler(event:DragEvent):void
{
event.preventDefault();
tree.hideDropFeedback(event);
}
protected function tree_dragOverHandler(event:DragEvent):void
{
if (event.dragInitiator == list)
{
event.preventDefault();
tree.showDropFeedback(event);
}
}
]]>
</fx:Script>
<s:layout>
<s:HorizontalLayout horizontalAlign="center" verticalAlign="middle" />
</s:layout>
<mx:List dataProvider="{listDataProvider}" dragComplete="list_dragCompleteHandler(event)" dragEnabled="true"
dragMoveEnabled="true" dropEnabled="true" id="list" width="200" />
<mx:Tree dataProvider="{treeDataProvider}" dragDrop="tree_dragDropHandler(event)" dragEnabled="true"
dragEnter="tree_dragEnterHandler(event)" dragExit="tree_dragExitHandler(event)"
dragOver="tree_dragOverHandler(event)" dropEnabled="true" id="tree" showRoot="true" width="200" />
</s:Application>

Resources