Custom external itemRenderer is receiving null objects from dataProvider - actionscript-3

I have a custom external itemRenderer which I use to display items in a mx:List. The dataProvider is an Array that contains 4 attributes per element. It seems as if the itemRenderer is, in fact, getting the Array because it displays 4 items(the amount of items in the Array) but the items are displayed as "[object Object]".
Here is my itemRenderer...
<mx:Metadata>
[Event(type="classes.events.RemoveEntryEvent", name="removeProject")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import classes.events.RemoveEntryEvent;
import mx.controls.Alert;
import mx.events.CloseEvent;
import mx.events.FlexEvent;
override public function set data (value:Object):void{
super.data = value;
//Alert.show(value.toString());
}
public function button_clickHandler():void {
var alertListener:Function = function(closeEvent:CloseEvent):void{
if (closeEvent.detail == Alert.YES){
//dispatchEvent(new RemoveEntryEvent(RemoveEntryEvent.REMOVE_PROJECT, true, false, data));
}
}
var myAlert:Alert = Alert.show("Are you sure you want to remove yourself from this project?",
"Remove Project",
(Alert.YES | Alert.CANCEL),
null, alertListener);
myAlert;
}
private function text_clickHandler():void{
Alert.show("inside text_clickHandler()");
}
]]>
</mx:Script>
<!-- The mx:Text should display a hand maybe when rolledOver: !buttonMode, -->
<mx:Text id="text" width="85%" text="{data}" fontThickness="5" click="text_clickHandler()"/>
<mx:Button id="removeButton" label="Remove" fontSize="9" width="63" verticalCenter="0" fontWeight="normal" x="329"
height="17" click="button_clickHandler()"></mx:Button>
</mx:Canvas>
When I step through the set data function, the 'value:Object' is null! But again, it is displaying the correct amount of items.
Here is my mxml code in which my mx:List is contained...
<mx:TitleWindow y="10" width="550" height="342" layout="absolute" title="LIST OF PROJECTS" cornerRadius="4" id="listOfProjects_panel" horizontalCenter="0">
<mx:List alternatingItemColors="{altColors}" x="65.5" y="30" width="399" height="232" backgroundColor="#F8F8F8" fontSize="12" dataProvider="{xmlSimpleArray}"
id="list_of_projects_master" initialize="listInitializer()" useRollOver="false" selectable="false">
</mx:List>
<mx:Button y="270" label="Refresh List" width="130" x="334.5" id="auth_btn_master0" fontWeight="normal"/>
<mx:Label x="65.5" y="10" text="Click To Select A Project:" fontWeight="bold"/>
</mx:TitleWindow>
Here is the initializer in my mx:Script...
private function listInitializer():void{
//list_of_projects_master.dataProvider = xmlSimpleArray;
list_of_projects_master.itemRenderer = new ClassFactory(ProjectListRenderer);
list_of_projects_master.addEventListener(RemoveEntryEvent.REMOVE_PROJECT, updateXML);
}
If anymore information is needed to assess the issue, please let me know

change the below line in itemrenderer
<mx:Text id="text" width="85%" text="{data}" fontThickness="5" click="text_clickHandler()"/>
shoul be like
<mx:Text id="text" width="85%" text="{data.labelfieldname}" fontThickness="5" click="text_clickHandler()"/>
hope this helps.

Related

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)" />

Flex update XML

im new to flex development and in need of assistance.
I have a xml file that contains data that i would like to update if the user changes anything, the file is saved on his local program files where the application is.
Here is my code that reads the XML file:
<fx:Declarations>
<s:HTTPService id="systemData" url="data/system.xml" method="POST"/>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[Bindable]
private var systemInfo:Object = new Object();
private var interval:uint;
[Bindable]
private var xmlData:ArrayCollection = new ArrayCollection();
private function viewMain(event:Event):void
{
mainWindow.visible = true;
systemWindow.visible = false;
}
private function viewSystem(event:Event):void
{
mainWindow.visible = false;
systemWindow.visible = true;
}
public function init():void
{
systemData.addEventListener(ResultEvent.RESULT, getXML);
systemData.send();
interval = setInterval(reloadXML, 1800000);
}
private function getXML(e:ResultEvent):void
{
systemInfo = systemData.lastResult.system;
systemIP.text = systemInfo.systemip;
systemPort.text = systemInfo.systemport;
systemUsername.text = systemInfo.systemusername;
systemPassword.text = systemInfo.systempassword;
}
private function reloadXML():void
{
systemData.send();
}
]]>
</fx:Script>
<s:BorderContainer id="mainWindow" width="100%" height="100%" visible="false">
<s:Button x="434" y="102" label="System Settings" click="viewSystem(event)"/>
<s:Button x="468" y="147" label="Button" />
</s:BorderContainer>
<s:BorderContainer id="systemWindow" width="100%" height="100%" visible="true">
<s:Panel width="800" height="600" horizontalCenter="0" title="System Settings"
verticalCenter="0">
<s:Label x="33" y="41" text="Server IP:"/>
<s:Label x="33" y="66" text="Port:"/>
<s:Label x="33" y="90" text="Username:"/>
<s:Label x="33" y="115" text="Password:"/>
<s:TextInput x="182" y="31" width="250" id="systemIP"/>
<s:TextInput x="182" y="56" width="250" id="systemPort"/>
<s:TextInput x="182" y="80" width="250" id="systemUsername"/>
<s:TextInput x="182" y="105" width="250" id="systemPassword"/>
<s:Button x="345" y="135" label="Save to XML" />
<s:Button x="718" y="-26" label="Main" click="viewMain(event)"/>
</s:Panel>
</s:BorderContainer>
The XML File:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<system>
<systemip>127.0.0.0</systemip>
<systemport>80</systemport>
<systemusername>rootu</systemusername>
<systempassword>passu</systempassword>
</system>
Thanks in advance
To write the updated content back in your xml file, you need to write the file back. I assume your application is an Adobe AIR application. You can make use of "File" class to read and write the content.
Link: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/filesystem/File.html

flex spark list Drag and drop an item on a spark canvas component

i have a spark list that displays a list of images that represent products. i am trying to implement a drag and drop functionality that allows the user to drag the products he wants to buy from the list to canvas area where he can see the products he choose before buying them. i am using the code below but i cannot figure out what is wrong with it , it seems that i am unable to use the list item as a draginitiator, can any one help please:
private function onMouseDown( event : MouseEvent ) : void
{
var list:List = List(event.currentTarget);
var dragInitiator:Image = Image (list.selectedItem);
var source : DragSource = new DragSource();
source.addData(dragInitiator, "img");
DragManager.doDrag(dragInitiator, source, event);
}
protected function canvas1_dragEnterHandler(event:DragEvent):void
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
protected function canvas1_dragDropHandler(event:DragEvent):void
{
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY; }
<fx:Model id="categoriesModel" source="Data/Categories.xml"/>
<s:ArrayList id="CategoriesCollection" source="{categoriesModel.Category}"/>
<fx:Model id="productsModel" source="Data/Products.xml"/>
<s:ArrayList id="ProductsCollection" source="{productsModel.Product}" />
</fx:Declarations>
<s:VGroup gap="5" horizontalAlign="center">
<s:HGroup gap="5">
<Components:PROExpressLogo/>
<s:List id="categoryList" scroller="{null}" visible="true"
itemRenderer="Renderers.categoryItemRenderer" width="700" borderAlpha="0"
change="categoryList_changeHandler(event)">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
</s:List>
</s:HGroup>
<s:List id="productList" scroller="{null}" contentBackgroundAlpha="0.4" contentBackgroundColor="0xabcdef"
itemRenderer="Renderers.productItemRenderer" width="880" borderAlpha="0" visible="true" horizontalCenter="0"
dragEnabled="false" mouseDown="onMouseDown(event)"
>
<s:layout>
<s:HorizontalLayout/>
</s:layout>
</s:List>
<s:HGroup gap="20">
<s:Group>
<s:Image id="planImage" width="500" height="300" horizontalCenter="0"
toolTip="Drag your items on your Plan and drop them were you plan to install them"
/>
<mx:Canvas width="500" height="300" backgroundAlpha="0.1"
backgroundColor="#abcdef" borderColor="#abcdef" borderStyle="inset"
contentBackgroundColor="#abcdef" cornerRadius="10"
dragDrop="canvas1_dragDropHandler(event)"
dragEnter="canvas1_dragEnterHandler(event)" dropShadowVisible="true"
horizontalCenter="0"/>
</s:Group>
<s:List id="cart" width="200" height="300"/>
</s:HGroup>
I 'm thinking you need add drag initiator should be the item renderer that you are dragging rather than the entire List control.
Not list.selectedItem that simple object that is not like UIComponent or VisualElement you have to point some ui component like group.

Flex:How to prompt an alert before navigating to any other page

How to ask user confirmation before highlighting/navigating to another panel/page?
I have few panels in my screen. Each panel has many controls. I would like to prompt a message box(or alert) with Ok and Cancel buttons, and take confirmation whenever user clicks on another panel.
If user clicks on "Ok" button then navigate to another panel/page.
If user clicks on "Cancel" button then remove the alert and focus to the same Panel.
Currently I have implemented this using panel's focus_out event(focusOutHandler(event:FocusEvent)). I click on the button which is in the another panel, now I got alert, but when i clicked on "OK" in the alert , nothing is happening(button click is event is not fired)
Thanks in advance
From the sounds of it you want to react depending on which button on the alert is clicked?
If that is the case, use the in-built close handler in the Alert class.
The Alert class has a static method show, with the following signature:
public static function show(text:String = "", title:String = "", flags:uint = 0x4, parent:Sprite = null, closeHandler:Function = null, iconClass:Class = null, defaultButtonFlag:uint = 0x4, moduleFactory:IFlexModuleFactory = null):Alert
By adding two flags with the pipe operator in the flags argument
Alert.OK || Alert.CANCEL and then adding your close handler in the closeHandler argument, you can inspect which button was clicked and react accordingly.
Something like this:
Alert:
Alert.show("Alert Title","Would you like to proceed?",Alert.OK || Alert.CANCEL,this,onClose)
onClose Function:
private function onClose(event:CloseEvent)
{
if (eventObj.detail==Alert.OK)
{
//proceed
}
else
{
//cancel operation
}
}
As per your comment on James post here i am posting sample, not sure if you are looking for the same: - Hope below code may give you some idea.
<?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>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.CloseEvent;
private var storeNextFocusID:String = "first";
private var storePreviousFocusID:String = "first";
private function firstFocus():void
{
first.setFocus();
storePreviousFocusID = first.name;
}
private function showFirstTimeAlert(event:MouseEvent):void
{
if(event.currentTarget.name != storePreviousFocusID)
{
Alert.show("Do you want to change Tab?","Alert",Alert.OK|Alert.CANCEL,null,closeHandler)
storeNextFocusID = event.currentTarget.name;
}
}
private function closeHandler(event:CloseEvent):void
{
if(event.detail == Alert.OK)
{
var focusCont:HGroup = mainContainer.getChildByName(storeNextFocusID) as HGroup;
focusCont.setFocus();
storePreviousFocusID = storeNextFocusID;
} else
{
}
}
]]>
</fx:Script>
<s:VGroup id="mainContainer" x="50" y="50" width="400" height="300" creationComplete="firstFocus()">
<s:HGroup id="first" name="first" width="100%" height="100%" click="showFirstTimeAlert(event)">
<mx:TabNavigator width="100%" height="100%">
<mx:VBox label="left">
<mx:Label text="labelPlacement = 'left'" />
</mx:VBox>
<mx:VBox label="right">
<mx:Label text="labelPlacement = 'right'" />
</mx:VBox>
</mx:TabNavigator>
<s:Panel width="100%" height="100%">
</s:Panel>
</s:HGroup>
<s:HGroup id="second" name="second" width="100%" height="100%" click="showFirstTimeAlert(event)">
<mx:TabNavigator width="100%" height="100%">
<mx:VBox label="top">
<mx:Label text="labelPlacement = 'top'" />
</mx:VBox>
<mx:VBox label="bottom">
<mx:Label text="labelPlacement = 'bottom'" />
</mx:VBox>
</mx:TabNavigator>
<s:Panel width="100%" height="100%">
</s:Panel>
</s:HGroup>
</s:VGroup>
</s:Application>

Heirarchical davanced datagrid with itemrenderer in flex4

I had done Hierarchical advanced data grid with image and button renderers using itemRenderers.
Herer the link for image:- Image
In the attached image, u can see the item renderes are not aligned properly. i had read few updates from this blog and applied spark renderer for creating item renderer class.
I created itemrenderer uisng s:MXAdvancedDataGridItemRenderer class.
Please check the below code for button renderer class :-
<s:layout>
<s:HorizontalLayout verticalAlign="middle" horizontalAlign="center" paddingLeft="6" paddingTop="0" paddingRight="6" paddingBottom="0"/>
</s:layout>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.common.ImageLibrary;
import mx.controls.Alert;
import mx.resources.ResourceManager;
override public function set data(value:Object):void
{
super.data = value;
var showButton:String;
if(value.hasOwnProperty("Data_Transfer") )
{
showButton = value.Data_Transfer;
if (showButton == "Show_Button") {
startId.visible= true;
startId.includeInLayout= true;
abortId.visible= true;
abortId.includeInLayout= true;
imgStatus.visible=false;
lblStatus.visible= false;
imgStatus.includeInLayout= false;
lblStatus.includeInLayout= false;
}else {
startId.visible= false;
abortId.visible= false;
startId.includeInLayout= false;
abortId.includeInLayout= false;
imgStatus.includeInLayout= true;
lblStatus.includeInLayout= true;
lblStatus.text = "--";
}
}
}
]]>
</fx:Script>
<s:HGroup width="100%" gap="5" verticalAlign="middle" horizontalAlign="left" height="100%">
<!--<mx:Image id="imgStatus"/>
<s:Label id="lblStatus" textAlign="left" showTruncationTip="true" paddingTop="3"/>-->
<s:VGroup height="50%" verticalAlign="middle" horizontalAlign="center">
<s:Button label="Start" id="startId"/>
<s:Button label="Abort" id="abortId" />
</s:VGroup>
<s:HGroup height="100%">
<mx:Image id="imgStatus" includeInLayout="false"/>
<s:Label id="lblStatus" textAlign="left" showTruncationTip="true" paddingTop="3" />
</s:HGroup>
</s:HGroup>
`
and the renderer is also not working properly. i have to show the buttons in the parent row and show the label and image in the child row. but the renderer is not working peroperly.
please let me know , if have any solution for this issue.