Question

How can I open a synchronous dialog in Flex? I need to call a function from an External Interface (JavaScript) that will open a simple dialog in the Flex application and returns an value according to the button the user has clicked (OK/Cancel).

So it should by a synchronous call to a dialog, i.e. the call waits until the user has closed the dialog like this.

//This function is called by JavaScript
function onApplicationUnload():Boolean
{
  var result:Boolean;
  result = showDialogAndWaitForResult();
  return result
}

Does anybody know how I can do this? I could write a loop that waits until the dialog has set a flag and then reads the result to return it, but there must be something that is way more elegant and reusable for waiting of the completion of other asynchronous calls.

EDIT: Unfortunately a callback does not work as the JavaScript function that calls onApplicationUnload() itself has to return a value (similar to the onApplicationUnload() function in Flex). This JavaScript function has a fixed signature as it is called by a framework and I cannot change it. Or in other words: The call from JavaScript to Flex must also be synchronous.

Was it helpful?

Solution

You can't do that in Flex. As David mentioned, Flex is single-threaded, so you can't have your function block while the dialog is being processed.

Your best bet might be to use a Javascript popup. You'll have a lot less control over the window, but it should behave the way you want (blocking the function until it's been closed).

OTHER TIPS

Flex doesn't work in a synchronous fashion, as it is a single thread application and so needs your code to hand execution back to the "core" in order to handle user input etc.

The way to do it is to make your dialogue's behaviour asynchronous:

function onApplicationUnload():void
{
    showDialog(resultMethod);
}

function resultMethod(result:Boolean):void
{
    ExternalInterface.call("javaScriptCallback", [result]);
}

Have your Flex code use an event to wait for the dialog. In the main thread, register an event handler that waits for the dialog to close. On OK in the dialog, dispatch the dialog complete event.

With Cairngorm, this is something like:

In the main thread:

CairngormEventDispatcher.getInstance().addEventListener(ClosingDialogCompleteEvent.DIALOG_COMPLETE, onClosingDialogComplete);

(if you want to avoid returning until complete, loop on a timer and global variable.)

In the dialog closing handler:

CairngormEventDispatcher.dispatchEvent(new ClosingDialogCompleteEvent(<parameters>));

The event handler:


public function onClosingDialogComplete (e: ClosingDialogCompleteEvent):void
{
   param1 = e.param1;
   param2 = e.param2;
   // etc.
   // Continue processing or set the global variable that signals the main thread to continue.
}

For this to work, the class ClosingDialogCompleteEvent has to be defined. Partial code for the class is:


package com. ... .event  // You define where the event lives.
{
import com.adobe.cairngorm.control.CairngormEvent;

public class ClosingDialogCompleteEvent extends CairngormEvent
{
    // Event type.
    public static const DIALOG_COMPLETE:String = "dialogComplete";

    public var param1:String;
    public var param2:String;

    public function ClosingDialogCompleteEvent(param1:String, param2:String)
    {
        super(DIALOG_COMPLETE);
        this.param1 = param1;
        this.param2 = param2;
    }
}
}

Waiting on an event is the best way to synchronize in Flex. It works well for startup dialogs too. In a flex-only application it works especially well.

I have explained a workaround to create synchronous alert in flex

http://reallypseudorandom.blogspot.com/2010/05/flash-asynchronous-alert-and-pause.html

OK... after all I found a possible solution. But I guess hardly everybody is going to do that seriously :-(

The solution focuses around using a while loop to check for a result and then return the function that is being called by JavaScript. However we need a way to sleep in the while loop, while we are waiting for the result. However calls to JavaScript are synchronous. Now the trick is to make a sleep in JavaScript, which is also not directly available here, but can be done using a synchronous XML Http Request like described on this blog.

As I said - I won't recommend this only as last resort. For my problem I have resorted to ugly JavaScript popups.

Have your dialog call another function in flex to process the result of the user selection:

private function deleteFileCheck():void
{
  Alert.show("Are you sure you want to delete this file?",
             "Confirm Delete",
             Alert.YES| Alert.NO,
             this, deleteFileHandler, null, Alert.NO);
}

private function deleteFileHandler(event:CloseEvent):void
{
    if (event.detail == Alert.YES)
    {
        ...do your processing here
    }
}

You can fake a synchronous dialog in flex by popping up a dialog then disabling everything in the background. You can see this in action if you do Alert.show("Hello World"); in an application. The background will grey out and the user won't be able to click on any UI in the background. The app will "wait" until the user clicks the OK button.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top