Lose data in draggable List with nested ItemRenderers - actionscript-3

I am suffering from this problem for a few days.
There is a List in which you can drag items.
[Bindable] public static var posts:ArrayCollection = new ArrayCollection();
[Bindable] private var dragit:Boolean = false;
protected function lst_itemClickHandler(evt:ItemClickEvent):void {
if (evt.label == 'mousedown') {
dragit = false;
return;
}
if (evt.label == 'mouseup') {
dragit = true;
return;
}
}
<s:List id="list" width="100%" height="100%" dataProvider="{posts}" itemRenderer="postIR" selectedIndex="0" dragEnabled="{dragit}" dragMoveEnabled="true" dropEnabled="true" useVirtualLayout="false"/>
This list have an item renderer (postIR) as part of which buttons, images, TextArea and another Tile List with his item renderer - socIR.
Here is postIR:
<?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"
xmlns:c="*"
autoDrawBackground="true" creationComplete="itemrenderer1_creationCompleteHandler(event)" maxHeight="120">
<fx:Script>
<![CDATA[
[Bindable] private var index:int;
[Bindable] private var socDP:ArrayCollection;
protected function itemrenderer1_creationCompleteHandler(event:FlexEvent):void
{
index = ((this.owner as List).dataProvider as ArrayCollection).getItemIndex(data);
socDP = Copypaste.socialVector[index] as ArrayCollection;
soc.addEventListener(ItemClickEvent.ITEM_CLICK, soc_itemClickHandler);
}
//Deleted some code
]]>
</fx:Script>
<c:CheckList id="soc" width="100%" height="100%" itemRenderer="socIR" mouseDown="txt_mouseDownHandler(event)" mouseUp="soc_mouseUpHandler(event)"
dataProvider="{socDP}" allowMultipleSelection="true" useVirtualLayout="false" click="soc_clickHandler(event)">
<c:layout>
<s:TileLayout requestedColumnCount="3" verticalAlign="top" padding="5"/>
</c:layout>
</c:CheckList>
//Deleted some code
</s:ItemRenderer>
Here is socIR:
<?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" click="itemrenderer1_clickHandler(event)" creationComplete="itemrenderer1_creationCompleteHandler(event)">
<s:layout>
<s:HorizontalLayout verticalAlign="middle" padding="5"/>
</s:layout>
<s:states>
<s:State name="normal"/>
<s:State name="selected"/>
</s:states>
<fx:Script>
<![CDATA[
protected function itemrenderer1_clickHandler(event:MouseEvent):void
{
if (this.selected) {
data.selected = true;
} else {
data.selected = false;
}
var parentList:List = owner as List;
var e:ItemClickEvent = new ItemClickEvent(ItemClickEvent.ITEM_CLICK, true);
e.item = data;
e.index = parentList.dataProvider.getItemIndex(data);
e.label = "selected";
dispatchEvent(e);
}
override public function set data(value:Object):void
{
super.data = value;
if (value.selected) {
data.selected = true;
} else {
data.selected = false;
}
}
protected function itemrenderer1_creationCompleteHandler(event:FlexEvent):void
{
if (data.selected) {
this.selected = true;
} else {
this.selected = false;
}
}
]]>
</fx:Script>
<s:CheckBox id="socCheck" selected.selected="true" selected.normal="false" mouseEnabled="false"/>
<s:Image source="{'images/socialicons/' + data.icon}"/>
<s:Label text="{data.label}"/>
</s:ItemRenderer>
Everything works fine until I need to drag an items in main List. Selected items in socIR or disappear or randomly shuffled. I used a variety of methods - to store data when changing items in the main class in the vector for each itemrenderers - public static var socialVector:Vector. = new Vector.();
, but it only adds to the confusion. I experimented with useVirtualLayout, but it did not help.
Please any advice how to avoid issue with data loss when drag an item.
Thanks.
PS so looks my list

Related

Flex/AIR: Native drag'n'drop on sub-application triggers wrong event handlers

I have two Flex applications (App1, App2) that I want to use as separate apps (no problem here) but the first app should also be able to load the second app in its window (no problem either). Both apps accept native drag'n'drop (onDragIn, onDragDrop). However, when I load App2 as sub-application (multi-versioned) its drag'n'drop handlers are not being called but instead those of App1. What am I missing here?
<!-- MAIN APP (App1) -->
<?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"
creationComplete="onComplete()">
<fx:Script>
<![CDATA[
import mx.controls.SWFLoader;
import mx.events.FlexEvent;
import mx.managers.DragManager;
internal var app2:App2=null;
internal var _show2nd:Boolean=false;
protected function onComplete():void
{
addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, onDragIn);
addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, onDragDrop);
var context:LoaderContext = new LoaderContext();
context.securityDomain = SecurityDomain.currentDomain;
context.applicationDomain = new ApplicationDomain();
if (app2 == null) app2 = new App2();
contentLoader.loadForCompatibility = true;
contentLoader.loaderContext = context;
}
private function onDragIn(e:NativeDragEvent):void
{
if (e.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT) &&
(e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array).length > 0)
DragManager.acceptDragDrop(this);
}
private function onDragDrop(e:NativeDragEvent):void
{
var a:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
(File(a[0]).extension == 'a') ? doThis() : doThat();
}
public function get show2nd():Boolean
{
return _show2nd;
}
public function set show2nd(b:Boolean):void
{
if (!b)
{
_show2nd = false;
contentLoader.unloadAndStop();
return;
}
contentLoader.source = app2;
_show2nd = true;
}
]]>
</fx:Script>
<s:Button click="{show2nd = !show2nd}"/>
<mx:SWFLoader id="contentLoader"/>
</s:WindowedApplication>
<!-- SUB APP (App2) -->
<?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"
creationComplete="onComplete()">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.managers.DragManager;
protected function onComplete():void
{
addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, onDragIn);
addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, onDragDrop);
}
private function onDragIn(e:NativeDragEvent):void
{
if (e.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT) &&
(e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array).length > 0)
DragManager.acceptDragDrop(this);
}
private function onDragDrop(e:NativeDragEvent):void
{
var a:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
(File(a[0]).extension == 'a') ? doThis() : doThat();
}
]]>
</fx:Script>

Create Custom Dialog Box using dispatch events,states and titlewindow in flex/AS3.0

Since a month Iam working on creating a custom dialog box, having parameters like message,state and modal(true/false)
Eg:
showAlert("Hi, how are you doing","Goodmorning", true);
I have learned how to dispatch event. but unable to dispatch the alertevent/popupManager using States.
Below is the code, I am struggling with.
Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function onclick(event:MouseEvent):void
{
this.dispatchEvent("Hi, How are you?", "Morning", true);
}
public function dispatchEvent(arg1:String, arg2:String, arg3:Boolean):void
{
var str:*=null;
str.message = arg1;
str.stateName = arg2;
str.modal = arg3;
this.dispatchEvent(new ShowAlert(ShowAlert.SHOW, true));
}
]]>
</mx:Script>
<mx:Button id="click" click="onclick(event)"/>
</mx:Application>
ShowAlert.as
package
{
import flash.events.*;
public class ShowAlert extends Event
{
public var _stateName:String;
public var _closable:Boolean;
public var _message:String;
public var _isModal:Boolean;
public static const SHOW:String="show";
public function flash.events.(arg1:String, arg2:Boolean=false, arg3:Boolean=false)
{
super(arg1, arg2, arg3);
trace("arg1: "+arg1+"\t arg2: "+arg2+"\t arg3: "+arg3);
}
public function set message(arg1:String):void
{
this._message = arg1;
}
public function get message():String
{
return _message;
}
public function get modal():Boolean
{
return _isModal;
}
public function get stateName():String
{
return _stateName;
}
public function set stateName(arg1:String):void
{
this._stateName = arg1;
}
public function set modal(arg1:Boolean):void
{
this._isModal = arg1;
}
public override function clone():flash.events.Event
{
return new ShowAlert(type);
}
}
}
I was unable to write the custom titlewindow using states, so I dint post that.
Please let me know, how to make this happen.
Below is the Sample code, specifying my problem
main.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
public var info:IModuleInfo;
public var loadalert:DisplayObject;
import mx.modules.ModuleManager;
import mx.modules.IModuleInfo;
import mx.events.ModuleEvent;
public function init():void
{
Alert.show("This is forst alert.");
}
public function Loadalerrt():void
{
trace("loadalertmodule");
info = ModuleManager.getModule("../bin-debug/alerrtmod.swf");
info.addEventListener(ModuleEvent.READY, modEventHandler);
info.load();
}
public function modEventHandler(event:ModuleEvent):void
{
trace("modeventHandler");
loadalert=info.factory.create() as DisplayObject;
can1.addChild(loadalert);
}
]]>
</mx:Script>
<mx:Button label="Alert in Application" id="b1" click="init()" x="29" y="21"/>
<mx:Button label="Load Module" id="b2" click="Loadalerrt();" x="10" y="92"/>
<mx:Canvas id="can1" x="409" y="57" backgroundColor="cyan"/>
</mx:Application>
alerttmod.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
public function alertshow():void
{
Alert.show("This is second alert, You Can see it covers whole application, What I want is its scope should be limited to this specific module, not to whole application ");
}
]]>
</mx:Script>
<mx:Button label="Alert in Module" id="b1" click="alertshow()" x="163" y="100"/>
</mx:Module>
Now I see your problem. I think it is not possible to restrict the modal area of the Alert. I can suggest you to fake the modal behaviour by desabling the modules elements while your dialog is being shown.
May be it can help you...
Here are two components to demonstrate it:
//your module with another Alert
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.managers.PopUpManager;
public function alertshow():void
{
Alert.show("This is second alert...");
}
public function alertshow2():void
{
var customAlert:CustomAlert = new CustomAlert();
customAlert.addEventListener("CLOSED", onCustomAlertClosed);
this.enabled = false;
PopUpManager.addPopUp(customAlert, this, false);
PopUpManager.centerPopUp(customAlert);
}
private function onCustomAlertClosed(evt:Event):void
{
this.enabled = true;
}
]]>
</mx:Script>
<mx:Button label="Alert in Module" id="b1" click="alertshow()" x="163" y="100"/>
<mx:Button label="CustomAlert in Module" id="b2" click="alertshow2()" x="163" y="150"/>
<mx:Canvas width="100%" height="100%" backgroundColor="0xbbbbbb" alpha="0.8" visible="{!this.enabled}"/>
</mx:Module>
//simple CustomAlert as a Panel
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="300" height="200">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
protected function button1_clickHandler(event:MouseEvent):void
{
PopUpManager.removePopUp(this);
this.dispatchEvent(new Event("CLOSED"));
}
]]>
</mx:Script>
<mx:Button x="112" y="128" label="Close" click="button1_clickHandler(event)"/>
</mx:Panel>

How to set progress bar for each images in a multiple image uploader?

i am trying to complete a multiple image uploader. i completed the multiple image uploader partially... My project contain a title window,a data grid and 3 buttons(select,upload,cancel).And the data grid contain 3 columns(image preview,name,size). i also put two progress bar. One is showing total images upload progress.. And other is put as item render for each image upload progress seperately(that progress bar showed at the data grid name column and the label of that progress bar is the name of each image)..the first one is working perfectly..But the second item render progress bar is not working..How can i maintain it?? can any one help me?? pls...
my demo is given below..
http://demo.enfintech.net/MultipleFileUpload/
sometimes it is working properly.but more than 4 images are uploaded it is not working.. Means the progress bar is not working properly..but the images are uploaded..
My code is given below
<?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" creationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/mx";
global
{
font-weight: bold;
}
</fx:Style>
<fx:Script>
<![CDATA[
import flash.sampler.NewObjectSample;
import flash.utils.flash_proxy;
import flash.utils.setTimeout;
import mx.charts.renderers.AreaRenderer;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.events.Request;
import mx.utils.OnDemandEventDispatcher;
private var refAddFiles:FileReferenceList=new FileReferenceList;
private var fileReference:FileReference=new FileReference;
private var arrSelectList:Array=new Array();
private var arrRemoveItem:ArrayCollection=new ArrayCollection();
private var serverSideUrl:String="http://demo.enfintech.net/MultipleFileUpload/fileUploader/uploadFile.php";
// private var serverSideUrl:String="http://192.168.1.60/fileUploader/uploadFile.php";
private var list:Array=new Array();
public var urlReq:URLRequest;
private var refAddFilesLength:int=0;
private var timer:Timer;
private var i:int=0;
private var totalSize:Number=0;
private var isSelected:Boolean=false;
private var images:Object;
private var varSize:Number;
private var numPerc:Number;
public var crnt:Number;
private var fileSizeArray:Array=new Array();
private var fileSize:String;
public var maxm:Number;
private var temp:Number=0;
private var uploadBytes:Number=0;
private var temptotal:Number=0;
private var tempVarSize:Number=0;
private var maximumSize:Number=0;
private var currentSize:Number=0;
private var checkCloseClick:Boolean=false;
[Bindable] private var files:ArrayCollection = new ArrayCollection();
private var fileRefUploadFiles:FileReference=new FileReference;
private function init():void
{
Security.loadPolicyFile("http://demo.enfintech.net/crossdomain.xml");
progressBar2.visible=false;
refAddFiles.addEventListener(Event.SELECT,fileRefSelect);
urlReq = new URLRequest(serverSideUrl);
}
private function fileSelect(event:Event):void
{
Alert.show("");
}
private function fileRefSelect(event:Event):void
{
progressBar2.visible=false;
upload1();
isSelected=true;
}
private function fileRefCompleted(event:Event):void
{
fileReference=event.target as FileReference;
fileReference.removeEventListener(Event.COMPLETE, fileRefCompleted);
fileReference.addEventListener(IOErrorEvent.IO_ERROR,error);
if(fileReference.size!=0)
{
tet2.text=fileReference.size.toString();
varSize=fileReference.size;
var tempVarSizeInBytes:Number=varSize;
fileSizeArray.push(tempVarSizeInBytes);
totalSize=varSize;
varSize=varSize/1024;
fileSize=String(varSize.toFixed(1))+"Kb";
tempVarSize=varSize;
if(varSize>1024)
{
varSize=varSize/1024;
fileSize=String(varSize.toFixed(1))+"Mb";
tempVarSize=varSize;
}
else
{
}
temptotal+=tempVarSizeInBytes;
progressBar2.maximum=temptotal;
}
images= {fileName:fileReference.name,size:fileSize, preview:fileReference.data,close:fileReference.name, maximum:fileReference.size, currentValue:0};
files.addItem(images);
select.enabled=false;
if(checkCloseClick==true)
{
upload0.enabled=true;
}
else
{
}
i=0;
}
private function uploadFiles():void
{
if(files.length==0)
{
Alert.show("Please Select file(s)");
}
else
{
var n:int=files.length;
progressBar2.minimum=0;
if(i<n)
{
progressBar2.visible=true;
fileRefUploadFiles=refAddFiles.fileList[i];
fileRefUploadFiles.upload(urlReq);
fileRefUploadFiles.addEventListener(ProgressEvent.PROGRESS,onUploadProgress);
fileRefUploadFiles.addEventListener(Event.COMPLETE,fileRefUploadFilesComplete);
select.enabled=true;
upload0.enabled=false;
}
}
}
public function onUploadProgress(event:ProgressEvent):void
{
numPerc=Math.round(((event.bytesLoaded+uploadBytes)/temptotal)*100);
files[i].currentValue=event.bytesLoaded;
files[i].maXimumValue=event.bytesTotal;
progressBar2.setProgress(uploadBytes+event.bytesLoaded,temptotal);
progressBar2.validateNow();
progressBar2.label=("UPLOADING "+numPerc.toString()+"% ("+(i+1).toString()+"/"+list.length.toString()+")");
}
private function fileRefUploadFilesComplete(event:Event):void
{
uploadBytes=uploadBytes+Number(fileSizeArray[i]);
i++;
uploadFiles();
}
public function upload1():void
{
list=refAddFiles.fileList;
var i:int=0;
var n:int=list.length;
for(i; i < refAddFiles.fileList.length; i++)
{
list[i].addEventListener(ProgressEvent.PROGRESS,uploadItemRender);
currentSize=crnt;
list[i].addEventListener(Event.COMPLETE, fileRefCompleted);
list[i].load();
}
}
private function uploadItemRender(event:ProgressEvent):void
{
maximumSize=event.bytesTotal;
currentSize=event.bytesLoaded;
}
public function removeItem():void
{
var item:int=dgMain.selectedIndex;
files.removeItemAt(item);
}
private function cancelClick():void
{
fileRefUploadFiles.cancel();
if(files.length!=0)
{
files.removeAll();
fileRefUploadFiles.data.clear();
progressBar2.enabled=false;
}
}
private function browsebtn():void
{
var arr:Array = [];
arr.push(new FileFilter("Images", ".gif;*.jpeg;*.jpg;*.png"));
// fileReference.browse(arr);
refAddFiles.browse(arr);
}
private function titleWindowClose():void
{
var item:int=dgMain.selectedIndex;
files.removeAll();
progressBar2.visible=false;
checkCloseClick=true;
select.enabled=true;
}
]]>
</fx:Script>
<s:TitleWindow x="204" y="10" width="520" height="325" id="titleWindow"
skinClass="TitleSkin" title="File Uploader" close="titleWindowClose()">
<mx:DataGrid id="dgMain" x="0" y="0" width="518" height="237" allowMultipleSelection="true"
dataProvider="{files}" fontFamily="Arial" fontSize="12" headerHeight="0"
horizontalScrollPolicy="off" variableRowHeight="true">
<mx:columns>
<mx:DataGridColumn dataField="preview" headerText="Preview" width="40" paddingLeft="5" itemRenderer="ImageDatagrdItmRndr">
</mx:DataGridColumn>
<mx:DataGridColumn dataField="fileName" headerText="Name" width="380" itemRenderer="itmRndrPrgrsBar"/>
<mx:DataGridColumn dataField="size" headerText="Size" width="60"/>
<mx:DataGridColumn id="close" headerText="Size" width="40" itemRenderer="buttonClose"/>
</mx:columns>
</mx:DataGrid>
<mx:ProgressBar id="progressBar2" x="-1" y="237" width="518" barColor="haloblue"
labelPlacement="center" mode="manual" themeColor="#eaeaea"
trackColors="[white,halosilver]"/>
<s:Button id="select" bottom="5" width="87" height="30" label="Select files"
click="browsebtn()" fontFamily="Arial" fontSize="12" horizontalCenter="-91" skinClass="Skin.setButtonSkin"
/>
<s:Button id="upload0" bottom="5" width="79" height="30" label="Upload" click="uploadFiles()"
fontFamily="Arial" fontSize="12" horizontalCenter="0" skinClass="Skin.setButtonSkin"/>
<s:Button id="cancel" bottom="5" width="79" height="30" label="Cancel" fontFamily="Arial"
fontSize="12" horizontalCenter="91" skinClass="Skin.setButtonSkin"/>
</s:TitleWindow>
<s:VGroup>
<s:Label id="tet" color="red" visible="false"/>
<s:Label id="tet2" color="red"/>
</s:VGroup>
</s:Application>
my item render for progressbar is
<?xml version="1.0" encoding="utf-8"?>
<s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
focusEnabled="true" xmlns:aaronhardy="aaronhardy.*">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
protected function progressBar1_updateCompleteHandler(event:FlexEvent):void
{
SparkProgressBar.maximum=data.maximum;
SparkProgressBar.value=data.currentValue;
}
]]>
</fx:Script>
<aaronhardy:ProgressBar id="SparkProgressBar" maximum="{data.maximum}" minimum="0" skinClass="aaronhardy.ProgressBarSkin" left="0" right="0" top="0" bottom="0" updateComplete="progressBar1_updateCompleteHandler(event)"/>
<s:Label id="lblData" left="0" right="0" text="{dataGridListData.label}" verticalCenter="0"/>
</s:MXDataGridItemRenderer>
And the image itemrender is
<?xml version="1.0" encoding="utf-8"?>
<s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
focusEnabled="true">
<fx:Script>
<![CDATA[
]]>
</fx:Script>
<!-- <s:Label id="lblData" top="0" left="0" right="0" bottom="0" text="{dataGridListData.label}" />-->
<mx:Image left="5" width="31" height="20" source="{data.preview}"/>
</s:MXDataGridItemRenderer>
There are good site here. I wish to be helpful for you.
multiple-file-upload-with-as3-and-php
Flash-AS3-FileReference-Select-and-Upload-Multiple-Files

Dynamically added FormItem doesn't show error text

I am dynamically creating a form on runtime of my application. The content of my form item (lets call it MyFormItemContent) looks like this (simplified):
<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="100%" borderAlpha="0.0">
<fx:Declarations>
<utils:DataItemValidator dataItem="{referenceToDataItem}"
source="{this}"/>
</fx:Declarations>
<s:HGroup width="100%">
<s:TextInput width="100%" text="#{bindingToText}"/>
<s:CheckBox width="14" selected="{refToBoolean}"/>
</s:HGroup>
</s:BorderContainer>
and the the code for the the validator we are using. It works fine other parts of the application and debuging shows that a message exists but is not shown.
/**
* This class effectively does *not* validate the given 'value', but just returns
* his 'dataItem's attached messages.
*/
public class DataItemValidator extends Validator {
private var _dataItem:StatefulDataItem;
public function get dataItem():StatefulDataItem {
return _dataItem;
}
public function set dataItem(dataItem:StatefulDataItem):void {
_dataItem = dataItem;
ChangeWatcher.watch(_dataItem, "messages", function():void {
validate();
}, false);
validate();
}
override protected function doValidation(value:Object):Array {
if (!isInitialized()) return [];
// Clear results Array.
var results:Array = [];
// If dataItem has error indicator append all messages to result array.
if (dataItem && dataItem.messages) {
for each (var message:ResultMessage in dataItem.messages) {
results.push(new ValidationResult(message.isErroneous(), null, "", message.text));
}
}
return results;
}
public function isErroneous():Boolean {
if (!dataItem) return false;
return dataItem.isErroneous();
}
private function isInitialized():Boolean {
return (dataItem != null);
}
}
The code that declares the form looks like this:
<s:Form id="myForm" width="100%" height="100%">
<s:layout>
<s:FormLayout gap="-7" paddingBottom="2" paddingLeft="2" paddingRight="2"
paddingTop="2"/>
</s:layout>
</s:Form>
And finally, the item is added to the form like this:
var formItem:FormItem = new FormItem();
formItem.label = "some text";
formItem.addElement(new MyFormItemContent());
myForm.addElement(formItem);
If the validation of MyValidator has errors a red frame apears around the BorderContainer as intended. But unfortunatly the error text that should apear right to the form item doesn't. I'm thinkin it's a layout problem because I define the validator inside the form item content before adding it to the form. I've already debugged this and read documentations a lot.
I thought it would help to know how a FormItem is added to a Form if you declare it in mxml but I couldn't find information on that either.
<?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" creationComplete="application2_creationCompleteHandler(event)" xmlns:local="*">
<fx:Script>
<![CDATA[
import mx.charts.series.ColumnSeries;
import mx.collections.ArrayCollection;
import mx.containers.FormItem;
import mx.events.FlexEvent;
protected function application2_creationCompleteHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
for(var i:int = 0; i < 4; i++)
{
var formItem:FormItem = new FormItem();
formItem.label = "some text";
formItem.addElement(new MyFormItemContent());
myForm.addElement(formItem);
}
}
]]>
</fx:Script>
<s:Form id="myForm" width="100%" height="100%">
<s:layout>
<s:FormLayout gap="-7" paddingBottom="2" paddingLeft="2" paddingRight="2"
paddingTop="2"/>
</s:layout>
</s:Form>
</s:Application>
form item mxml file
<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="100%" borderAlpha="0.0" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="bordercontainer1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.events.ValidationResultEvent;
[Bindable]
private var bindingToText:String;
[Bindable]
private var refToBoolean:Boolean;
protected function bordercontainer1_creationCompleteHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
}
protected function txt_focusOutHandler(event:FocusEvent):void
{
var obj:ValidationResultEvent = validator.validate(txt.text);
error.visible = !(obj.type == "valid");
}
]]>
</fx:Script>
<fx:Declarations>
<mx:PhoneNumberValidator id="validator"/>
</fx:Declarations>
<s:HGroup width="100%">
<s:TextInput id="txt" width="100%" text="#{bindingToText}" focusOut="txt_focusOutHandler(event)"/>
<s:CheckBox width="14" selected="{refToBoolean}"/>
<s:Label id="error" visible="false" backgroundColor="red" text="This Field Required"/>
</s:HGroup>
</s:BorderContainer>
I am posting this code for your interest.

ItemRollOver with a custom ToolTip

I have this custom toolTip:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
implements="mx.core.IToolTip"
creationPolicy="all"
cornerRadius="4" borderStyle="solid" backgroundColor="#FFFFFF"
creationComplete="init()" width="100" height="100">
<fx:Script>
<![CDATA[
import mx.core.IToolTip;
public var arrItemsKits:Array=[];
public var _text:String;
public function get text():String {
return _text;
}
public function set text(value:String):void {
}
protected function init():void
{
grid.dataProvider=arrItemsKits;
}
]]>
</fx:Script>
<mx:DataGrid id="grid" width="100%" height="100%">
<mx:columns>
<mx:DataGridColumn headerText="Code" dataField="itemPartNumber"/>
<mx:DataGridColumn headerText="Description" dataField="kitItemsNotes"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
and i want it to fire it when i roll the mouse over a row from a datagrid, so i need to add an event listener(toolTipCreate) to the row of that grid.
Any ideas how can i solve this?
Thanks
Check out this
<!-- myDataGridTest.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.events.ListEvent;
import mx.core.IToolTip;
import mx.events.ToolTipEvent;
// holds the currently highlighted item
private var highlightedItem:Object;
// event listener to get our hands on the currently highlighted item.
private function getHighlightedItem(e:ListEvent):void {
highlightedItem = e.itemRenderer.data;
// Quick n dirty way to force the ToolTipManager to refresh our tooltip.
// We need to dispatch this by hand because the pointer never leaves myDataGrid
// between successive highlights.
myDataGrid.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OUT));
}
private function createTooltip(e:ToolTipEvent):void {
var tt:MyCustomTooltip = new MyCustomTooltip();
tt.firstName = highlightedItem.name;
tt.lastName = highlightedItem.surname;
// Contract with the tooltip manager: if it finds an IToolTip instance attached to
// the event, it uses that instance instead of creating the standard one.
e.toolTip = tt;
}
]]>
</mx:Script>
<mx:DataGrid id="myDataGrid" toolTip=" " toolTipCreate="createTooltip(event)" itemRollOver="getHighlightedItem(event)">
<mx:dataProvider>
<mx:Object name="john" surname="doe"/>
<mx:Object name="mike" surname="smith"/>
</mx:dataProvider>
</mx:DataGrid>
</mx:Application>
<!-- MyCustomTooltip.mxml -->
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" implements="mx.core.IToolTip"
backgroundColor="yellow" backgroundAlpha="0.6">
<mx:Script>
<![CDATA[
private var _firstName:String;
private var _lastName:String;
// Dummy implementations to comply with mx.core.IToolTip
public function get text():String {return null;}
public function set text(value:String):void {}
// properties and functions
public function set firstName(value:String):void {
_firstName = value;
invalidateProperties();
}
public function set lastName(value:String):void {
_lastName = value;
invalidateProperties();
}
override protected function commitProperties():void {
fName.text = _firstName;
lName.text = _lastName;
}
]]>
</mx:Script>
<mx:Label x="0" y="0" id="fName"/>
<mx:Label x="0" y="20" id="lName"/>
</mx:Canvas>
.
.
Or try something like this
.
.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="doInit();">
<mx:Script>
<!![CDATA[import mx.collections.ArrayCollection; // this holds the grid data
[Bindable]
private var myData:ArrayCollection = new ArrayCollection();private function doInit():void{
myData.addItem({fname:"Joe",lname:"Bloggs"});
myData.addItem({fname:"Joe1",lname:"Bloggs"});
}
private function buildToolTip(item:Object):String{
var myString:String = "";
if(item != null)
{
myString = myString + "Firstname : " + item.fname + "\n";
myString = myString + "Lastname : " + item.lname + "\n"
}
return myString;
}
]]>
</mx:Script>
<mx:DataGrid id="dGrid" dataProvider="{myData}" visible="true" dataTipFunction="buildToolTip">
<mx:columns>
<mx:DataGridColumn dataField="fname" headerText="FirstName" showDataTips="true" />
<mx:DataGridColumn dataField="lname" headerText="LastName" showDataTips="true" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
I figured it out: On itemRollOver handler you add event.itemRenderer.addEventListener(ToolTipEvent.TOOL_TIP_CREATE, createTT);