I understand how to declaratively assign a method to be called when an Image receives a MouseMove event.
<mx:Image
id="oneCent"
mouseMove="dragIt(event, 1);"
/>
How do I do this programmatically in Flex/AS3?
EDIT: Thanks for the comments. Here's what I have so far:
myImage = new Image();
myImage.id = "oneCent";
myImage.addEventListener(MouseEvent.MOUSE_MOVE, dragIt);
The code snippet above assigns the dragIt method to the MOUSE_MOVE event for myImage. So far, so good. How do I pass in the 2nd parameter to the call to dragIt?
You can't pass the second param directly - so add it to myImage:
myImage = new Image();
myImage.id = "oneCent";
myImage.num = 1;
myImage.addEventListener(MouseEvent.MOUSE_MOVE, dragIt);
Then in the dragit function:
function dragIt(event:MouseEvent):void {
trace("PARAM =", event.target.num, event.target.id);
}
Where event.target automatically becomes a reference to the image
oneCent.addEventListener(MouseEvent.MOUSE_MOVE, dragIt);
...
function dragIt(event:MouseEvent):void
{
...
You can't pass extra arguments to event handlers. Behind the scenes, the Flex compiler is generating code that looks something like this:
private function generatedMouseMoveHandler(event:MouseEvent):void
{
dragIt(event, 1);
}
Any event handler created in MXML will be wrapped like that. That's why you can refer to a variable named event.
Scott's got it, although it's even better (and cleaner!) to use an anonymous function:
oneCent.addEventListener(MouseEvent.MOUSE_MOVE, function(e:MouseEvent):void{
...
});
Which is better if you're not gonna use dragIt() later in your code.
Related
Can I add new method to aspxclienttextbox control?
I'm doing custom control on the aspxtextbox...
I wish to add client-side method on the custom control and i have no idea on it...
So anyone know how to make it?
I know of two methods to achieve this:
1.Add method to object prototype:
ASPxClientTextBox.prototype.NewMethod = function(param1) { console.log(param1); }
According to this ticket you should place this code at the end of body section.
2.Use ASPxTextBox ClientSideEvents.Init in your custom control code. This will dinamically register method for every ASPxTextBox instance (while first method modifies object prototype).
ClientSideEvents.Init = "function(s,e) {s.NewMethod = function(param1) { console.log(param1); }}";
I am using view stack...so when view change like when we move from one page to another hide event is dispatched.So i am saving the information of last page in hide event before i go to next page.but thing is that if i change nothing still change on view hide event is invoked nd call go to backend...i just want do call only if sumthing change in the view..like sum text value...So i have two options
use event listener on each component if sumthing change its make the flag true...nd hide event check, if flag is true send call to backend.
event listener at container level ..if sumthing change in child componenet through bubbling container knows if sum event is dispatched.nd makes the flag true.
I have doubt with container...
Can i use container, and how?
Reason why I can't use container?
What are the pros and cons either way?
I would recommend using a dataProvider with the ability to compare them. For instance, if you are changing things with textinputs, you could basically do something like this:
[Bindable]
private var myDataProvider:Object = new Object();
private function creationCompleteHandler():void {
myDataProvider.updated = false;
myDataProvider.defaultValue = 'default';
myDataProvider.defaultValueTwo = 'default';
}
etc.
Then, in your mxml, you can have something like this:
<mx:TextInput id="myText" text="{myDataProvider.defaultValue}" change="myDataProvider.defaultValue=myText.text; myDataProvider.updated=true;" />
Lastly, in your hide event, you can do the following:
private function hideEventHandler( event:Event ):void {
if( myDataProvider.updated ){
// Call your RemoteServices (or w/e) to update the information
}
}
This way, when anything changes, you can update your dataProvider and have access to the new information each time.
Hope this helps!
I've used an approach similar to your first option in a couple of my past projects. In the change event for each of my form's controls I make a call to a small function that just sets a changesMade flag to true in my model. When the user tries to navigate away from my form, I check the changesMade flag to see if I need to save the info.
Data models are your friend!
If you get in the habit of creating strongly typed data models out of your loaded data, questions like this become very basic.
I always have a key binding set to generate a code snipit similar to this...
private var _foo:String;
public function get foo():String
{
return _foo;
}
public function set foo(value:String):void
{
if(_foo == value)
return;
var oldVal:String = _foo;
_foo = value;
this.invalidateProperty("foo", oldVal, value);
}
If your data used getters/setters like this, it would be very easy to validate a change on the model level, cutting the view out of the process entirely.
How can I set a function to be called when the length of a DataProvider changes?
Here is a good solution using the event "CollectionEvent.COLLECTION_CHANGE" :
http://blog.flexexamples.com/2008/12/16/detecting-when-the-data-provider-of-a-datagrid-control-changes-in-flex/
If you're working with an ICollectionView (aka ArrayCollection), you could add an event listener for the "collectionChange" event.
Docs: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/collections/ListCollectionView.html#event:collectionChange
If you are inside an MXML document the dataProvider property of the UI component should be a source of data binding. So you could just {myComponent.dataProvider.length} bind the value to something else if that is the use case.
The only way I could get thru it was making a binding in the actionscript code. Something like this:
protected function creationCompleteHandler(event:FlexEvent):void {
BindingUtils.bindSetter(myHandleFunction, myList, "dataProvider");
}
myHandleFunction receives by parameter an object with the type of the binded property.
I have a spark List control. It has a dataProvider that shows reply from twitter search.
I have created a function for change handler like this:
protected function list_changeHandler(event:IndexChangeEvent):void
{
ta.text = coverflow.selectedItem.title;
}
So, whenever I select each of the items in the List, I will see the message(ta.text)
but now, instead of me manually clicking the first time, I want it to automatically click/select the first item and see the first message(ta.text)
How can I achieve this?
You should set the requireSelection property to true on the list control
<s:List id="myList" dataProvider="{myDataProvider}" requireSelection="true"/>
How about to try this solution? :)
Your list control also has event name creationComplete (similar to change event). Try to select your first item with this:
protected function list1_creationCompleteHandler(event:FlexEvent):void
{
if(event.target.dataProvider != null )
{
(event.target as List).selectedIndex = 0;
}
}
You may not need to convert event.target to List. but it may help you access code completion while you are coding.
Actually, in thinking about this, you probably need to subclass the list and override the dataProvider setter.
override public function set dataProvider(data:*) : void {
super._dataProvider = data;
// This will be an ArrayCollection or XMLListCollection, so will have a length
if (data && data.length > 0) {
this.selectedIndex = 0;
invalidateDisplayList();
}
}
Set the dataProvider of the list, set the selected item, and then either call your handler function directly with a null parameter, or make the list dispatch an indexChanged event so that your handler function gets executed.
I've done a lot of C# programming with both Winforms and WPF. I'm working on a Flex/Air app now for cross platform support. But this is my first flex project, so I'm learning as I go.
I've got a window that I want to popup, that the user will fill out a form, then hit OK or CANCEL. I set it up the same way I would've in C#, but it doesn't work, and I can't really see a way to make it do what I want.
EDIT:
So I'm trying events now, the events just don't seem to be handled...
EDIT again:
Oh, It's because the popup manager seems to create a new instance of the Form object, rather than using the one I created already.
so in the showWindow method, I put in this code rather than the popup manager:
parent.addChild(this);
then I remove it when I close it. The only problem is, it doesn't disable the rest of the parent like the popup manager does. Any suggestions on that?
PARENT:
private function btnAdd_Clicked():void
{
var form:Form = new Form();
form.addEventListener(CloseEvent.CLOSE, onFormClosed, false, 0, true);
recipeForm.showWindow(this);
}
private function onFormClosed(e:CloseEvent):void
{
//none of these Alerts are ever shown. I also tried breakpoints in debug to try an follow the code, with no luck
Alert.show("Closed");
if(e.detail == Alert.OK)
{
Alert.show("OK");
}
else if(e.detail == Alert.CANCEL)
{
Alert.show("Cancel");
}
}
CHILD:
private function btnCancel_Clicked():void
{
okClicked = false;
closeWindow();
}
public function closeWindow():void
{
var e:CloseEvent = new CloseEvent(CloseEvent.CLOSE);
e.detail = okClicked ? Alert.OK : Alert.CANCEL;
dispatchEvent(e);
PopUpManager.removePopUp(this);
}
public function showWindow(parent:WindowedApplication):void
{
var window:IFlexDisplayObject = PopUpManager.createPopUp(parent, RecipeForm, true);
PopUpManager.centerPopUp(window);
}
You can do this at least two different ways:
FIRST WAY: Using events
Let your Form class dispatch an event when either of the buttons is clicked. After Form is instantiated from the parent view, add an eventListener for the event(s) it's known to dispatch. When the Form dispatches the event, the eventListener will be invoked. You can even reuse Flex's CloseEvent and set the "detail" property to either Alert.OK or Alert.CANCEL before dispatching it.
In Form:
var e:CloseEvent = new CloseEvent(CloseEvent.CLOSE);
e.detail = okClicked ? Alert.OK : Alert.CANCEL;
dispatchEvent(e);
In parent:
var f:Form = new Form();
f.addEventListener(CloseEvent.CLOSE, onClose, false, 0, true);
...
private function onClose(e:CloseEvent):void
{
if (e.detail == Alert.OK)
// do something
else if (e.detail == Alert.CANCEL)
// do something else
}
SECOND WAY: Using callbacks
Add a public var of type "Function" to your Form class and supply a callback function from the parent. This does basically the same thing as #1 except with little less abstraction / indirection.
I would recommend #1 since the event model in Flex is pretty well-conceived and more flexible than the callback.
In Form:
var e:CloseEvent = new CloseEvent(CloseEvent.CLOSE);
e.detail = okClicked ? Alert.OK : Alert.CANCEL;
dispatchEvent(e);
In parent:
var f:Form = new Form();
f.addEventListener(CloseEvent.CLOSE, onClose, false, 0, true);
...
private function onClose(e:CloseEvent):void
{
if (e.detail == Alert.OK)
// do something
else if (e.detail == Alert.CANCEL)
// do something else
}
Not sure if this is still an open issue. I ran into this very same problem and I think I figured out what is wrong. At least I did for my problem.
I implemented things exactly as you did. I also have the close attribute set to closeWindow (I'm using a TitleWindow for my dialog).
So when the window is closed via the X at the top, it will call closeWindow, also if you click on the Cancel button, it will also call closeWindow.
The problem for me was that clicking cancel, dispatches a CloseEvent which seems to be caught by a Listener which calls closeWindow again (possibly via the close attribute which probably creates its own internal listener). I'm not sure if its an infinite loop but Flex does not like this.
My solution was to create two functions, one for the X close window to call and one for the Cancel button to dispatch a CloseEvent of its own. This seemed to work for me. Hope it helps you.