GWT 2.8 dropevent datatransfer null - datagrid

I'm trying to drag and drop an element from a DataGrid which is the widget of a FocusPanel. The target is another DataGrid which is the widget of another FocusPanel contained in a DialogBox. The method onDragStart works fine. I can check with the debugger (Firefox 53.0) that the dataTransfer object is populated with the setData method of the DragStartEvent. On the side of the target the onDrop method is correctly called. The issue is that the dataTransfer object is null and the getData method of DropEvent returns an error. I don't understand why the dataTransfer object is null.

I found the answer when reading the paragraph "Performing a Drop" on MDN "Drag Operations". There is a js code snippet where event.preventDefault() is placed at the end of the onDrop function. This drew my attention since my Java code is calling preventDefault() in the beginning of the onDrop() method. I moved the call to preventDefault() to the end of the method and it works. The dataTransfer is no more null and getData() returns the correct information.

Related

Cloning an object with Instantiate() loses the listeners

When cloning a button at runtime using Instantiate(), which contained listeners on it's onClick event, the listeners are not present in the clone.
The behaviour can be tested by having a Canvas with a button and this script attached:
void Start () {
var button = transform.GetChild (0);
button.GetComponent<Button> ().onClick.AddListener (new UnityAction(() => Debug.Log("Event triggered!")));
var button2 = Instantiate (button);
button2.SetParent (transform);
}
The cloned button will not print anything to the console when clicked.
Is there a way to clone a GameObject so that it retains event listeners?
Runtime listeners are not persistent and then not serialized. As a result they are not passed on when you clone the button.
Either you'd have to add the method to a script and attach the script to your prefab for it to be serialized along or assign it by code like you do for the first one.
Instantiation. When you call Instantiate() on either a prefab, or a
gameobject that lives in the scene, or on anything else for that
matter (everything that derives from UnityEngine.Object can be
serialized), we serialize the object, then create a new object, and
then we “deserialize” the data onto the new object. (We then run the
same serialization code again in a different variant, where we use it
to report which other UnityEngine.Object’s are being referenced. We
then check for all referenced UnityEngine.Object’s if they are part
of the data being Instantiated(). If the reference is pointing to
something “external” (like a texture) we keep that reference as it
is, if it is pointing to something “internal” (like a child
gameobject), we patch the reference to the corresponding copy).
http://blogs.unity3d.com/2014/06/24/serialization-in-unity/
As for AddListener
This function adds a "non persistent" delegate, which means it will not show up in the inspector, and will be forgotten when you exit play mode in the editor. These differ from "persistent" listeners which you can add during edit-time in the inspector, and which persist between edit and play mode.
https://docs.unity3d.com/ScriptReference/Events.UnityEvent.AddListener.html
For those reasons, I assume the non-persistent is not serialized and then not passed to the cloned object.

MXML-class initialization order

I have written a few custom components in Flex 4, and run into this issue a few times.
var myForm:MyForm = new MyForm;
myForm.SetData(data);
addElement(myForm);
Now Imagine I am calling these functions from a non-constructor function of a Panel or VGroup (or any other container). Annoyingly, during MyForm.SetData(), not all fields of myForm that are declared there are yet initialized. Such as:
<s:VGroup id="dataGroup">
If my SetData()-function wants to access dataGroup (for the reason to .addElement() the just recieved data to it), it just fails with a nullpointer exception, because dataGroup is not yet created, despite this being after the constructor. How can guarantee that the form was initialized fully?
Listening for the creationComplete event and adding your components in the handler for the event is one way to do this. This is what Sam DeHaan suggested.
Another way you can do this is to override the createChildren() function. This is the function that creates and adds all of a component's child components. Code would look something like this:
override public function createChildren():void
{
super.createChildren();
var myForm:MyForm = new MyForm;
// Note that data may be null here, best to
// override commitProperties() to set it.
myForm.SetData(data);
addElement(myForm);
}
The docs on the component lifecycle will provide a ton of detail on this topic.
Unless I'm misunderstanding your question,
You should put the code that runs into this null pointer exception in a creationComplete callback on the container that you need defined.

Flex - Why is my custom event not being registered with the following event listener?

printableInvoice.addEventListener(batchGenerated, printableInvoice_batchGeneratedHandler);
Results in this error:
1120: Access of undefined property batchGenerated. I have tried it as FlexEvent.batchGenerated and FlashEvent.batchGenerated.
The MetaData and function that dispatches the even in the component printableInvoice is all right. It I instantiate printableInvoice as an mxml component instead of via action-script it well let put a tag into the mxml line: batchGenerated="someFunction()"
Thanks.
batchGenerated should be a string.
It looks like your application dispatches an event whenever the batch is generated.
I'm assuming inside your code you have something along the lines of either:
dispatchEvent( new BatchEvent("batchGenerated") );
or
dispatchEvent( new BatchEvent(BatchEvent.BATCH_GENERATED) );
The second way is usually preferred as using variables instead of magic strings gives you an extra level of compile time checking.
The first required parameter of events is typically the type of the event - Event.CHANGE (aka "change"), FlexEvent.VALUE_COMMIT (aka "valueCommit") etc.
This is what the event listener is actually comparing against.
So in your event listener code above, you would want to change the line to be either:
printableInvoice.addEventListener("batchGenerated", printableInvoice_batchGeneratedHandler);
or hopefully
printableInvoice.addEventListener(BatchEvent.BATCH_GENERATED, printableInvoice_batchGeneratedHandler);
If you want to go further, the Flex documentation goes into some detail as to how the event system works, and how the events are effectively targeted and handled through the use of the Capture, Target, and Bubble phases.

stack overflow on XMLListCollection collectionEvent

I'm working on a Flex 3 project, and I'm using a pair of XMLListCollection(s) to manage a combobox and a data grid.
The combobox piece is working perfectly. The XMLListCollection for this is static. The user picks an item, and, on "change", it fires off an addItem() to the second collection. The second collection's datagrid then displays the updated list, and all is well.
The datagrid, however, is editable. A further complication is that I have another event handler bound to the second XMLLIstCollection's "change" event, and in that handler, I do make additional changes to the second list. This essentially causes an infinite loop (a stack overflow :D ), of the second lists "change" handler.
I'm not really sure how to handle this. Searching has brought up an idea or two regarding AutoUpdate functionality, but I wasn't able to get much out of them. In particular, the behavior persists, executing the 'updates' as soon as I re-enable, so I imagine I may be doing it wrong. I want the update to run, in general, just not DURING that code block.
Thanks for your help!
Trying to bind the behaviour to a custom event rather than the CHANGE event.
I.e. do what you are doing now, but dispatch and handle a custom event to do the work.
Have you considered using callLater?
Does direct manipulation of XMLListCollection's source XMLList have the same results?
Have you considered something like:
private function changeHandler( event:Event ):void
{
event.target.removeEventListener( event.type, changeHandler );
// your code here.
event.target.addEventListener( event.type, changeHandler );
}

Flex adding event listeners with callback functions which have no arguments

fileReference.addEventListener(Event.COMPLETE, uploadCompleteHandler);
private function uploadCompleteHandler(event:Event):void {}
Above is one way to add an event listener in Actionscript.
By default the callback function needs to have an argument with
name event and type Event.
Is there a way to declare this function without any arguments :
private function uploadCompleteHandler():void {}
Edit : It's possible to add an event handler without any arguments in mxml. So one student wanted to know, why isn't it possible to do the same in actionscript?
The reason is that in mxml what you write isn't actually the handler, is what gets executed in the handler. If you compile with -keep-generated-actionscript flag (To set it in Flex Builder right click to open the project Properties, select Flex Compiler, and add -keep-generated-actionscript to the Additional compiler arguments), you can see in the generated source for your component, that the compiler created a handler for that event, and the body is composed by that you wrote in mxml.
So if you have something like:
click="doSomething();"
You can already notice that you're actually giving an instruction there, that's not a method reference you're passing like when you use addEventHandler.
Then you'll have in the generated file something like:
private function myComponent_Click(evt : MouseEvent) : void
{
doSomething();
}
And somewhere else in the same file the adding of the event listener:
this.addEventListener(MouseEvent.CLICK, myComponent_Click);
Notice the second parameter is not a function result, it's a function reference, because the parenthesizes that denote a function call are missing, and our particular function is not a getter either.
You can also specify more calls in mxml, like:
click="doSomething(); doSomethingElse();"
You can even pass the event parameter to your method:
click="doSomething(event);"
Whatever you write in the value of the mxml event (not sure it's the right term to use) will become the body of the generated handler for the actionscript event.
No, you'll get a runtime exception when the event fires if you'll try to register it as event listener.
You may use the following syntax to allow calling your handler directly without event object:
private function uploadCompleteHandler(event:Event = null):void {}

Resources