views:

2295

answers:

7

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.

+2  A: 

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]);
}
David Arno
The JavaScript function that called onApplicationUnload() must also wait for the result to be able to return it. There is no way for me to change this on the JavaScript side as there I also have a function that needs to return a value that is passed to the application framework.
Yaba
Then - as Herms says - there is no way for you to use Flex to solve this problem and you'll need to look at using a JavaScript dialogue instead. Sorry about that.
David Arno
Thank you for your answer anyway.
Yaba
+2  A: 

You can't do that in Flex. As David metioned, 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 javscript 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).

Herms
A: 

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.

Yaba
A: 

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.

Mark Ingram
That's not the problem. The problem here is that the function continues to run, when it has opened the dialog and thus there is no real way to wait for the return value of the dialog that shall be returned by that function.
Yaba
Is this to be displayed when the page has closed?
Mark Ingram
Almost: It should be displayed right before the page is going to be closed. And based on the return code of the JavaScript call (which calls the Flex function that displays the dialog) the page will be left or not.
Yaba
A: 

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
    }
}
Phil
A: 

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.

Grafton
Still needs another function... That's not what I need. I need a function to be called and wait to return the result.
Yaba
A: 

I have explained a workaround to create synchronous alert in flex

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

arvind