User382
User382

Reputation: 874

Xamarin iOS WKWebView showing JavaScript Alert

I would like to show the JavaScript Alert in my WKWebView. I have implemented the IWKUIDelegate and its methods RunJavaScriptAlertPanel, RunJavaScriptConfirmPanel. These gets called for a JavaScript Alert. I would like to know how to handle the buttons and action on those buttons.

Is there a way i can write a generic UIAlertView for all JavaScript Alerts. For example below i have added errorAlert.AddButton("OK"); but in reality i don't know number of buttons and button title. Also how to handle the completionHandler action

    [Export ("webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:")]
    public void RunJavaScriptConfirmPanel (WKWebView webView, String message, WKFrameInfo frame,  Action<bool> completionHandler)
    {
        Console.WriteLine ("RunJavaScriptConfirmPanel");


        UIAlertView errorAlert = new UIAlertView();
        errorAlert.Title = "Alert";
        errorAlert.Message = message;
        errorAlert.AddButton("OK");
        errorAlert.Show();
    }

Upvotes: 2

Views: 2545

Answers (1)

J.Thoo
J.Thoo

Reputation: 171

I'm not sure where you're trying to handle the action, whether it is in javascript or with C# in the app, so I'll try to address both. The short answer is, let javascript handle it, and if need be, make a call back to the app from javascript once a selection has been made from the dialog.

Alert Example

    public override void RunJavaScriptAlertPanel(WKWebView webView, string message, WKFrameInfo frame, Action completionHandler)
    {
        var alert = UIAlertController.Create("Alert", message, UIAlertControllerStyle.Alert);
        alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));

        //Let javascript handle the OK click by passing the completionHandler to the controller
        ViewController.PresentViewController(alert, true, completionHandler);
    }

Confirm Example

    public override void RunJavaScriptConfirmPanel(WKWebView webView, string message, WKFrameInfo frame, Action<bool> completionHandler)
    {
        var alert = UIAlertController.Create("Please confirm", message, UIAlertControllerStyle.Alert);

        //Let javascript handle the OK click by passing the completionHandler to the controller
        alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, action => completionHandler(true)));
        //Let javascript handle the Cancel click by passing the completionHandler to the controller
        alert.AddAction(UIAlertAction.Create("Cancel", UIAlertActionStyle.Cancel, action => completionHandler(false)));

        ViewController.PresentViewController(alert, true, null);
    }

Prompt Example

    public override void RunJavaScriptTextInputPanel(WKWebView webView, string prompt, string defaultText, WKFrameInfo frame, Action<string> completionHandler)
    {
        var alert = UIAlertController.Create("Prompt", prompt, UIAlertControllerStyle.Alert);
        alert.AddTextField(textfield => { textfield.Placeholder = defaultText; });
        alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, action => completionHandler(alert.TextFields[0].Text)));
        alert.AddAction(UIAlertAction.Create("Cancel", UIAlertActionStyle.Cancel, action => completionHandler(null)));
        ViewController.PresentViewController(alert, true, null);
    }

So that gives you an example of how to pass the button clicks back to javascript. If you want javascript to make a call back, you'll need to register script handlers by subclassing from WKScriptMessageHandler. There's a basic example here https://forums.xamarin.com/discussion/41777/wkwebview-caching-not-working

Just as a note, UIAlertView has been deprecated. You might want to start using UIAlertController instead. See https://stackoverflow.com/a/32690371/5606840. If you want access to the view controller to display the alerts, pass it into your WKUIDelegate class at initialization.

Edit

To expand on how to handle the results in javascript

alert('This is an alert');

The webview will pause the javascript thread and call RunJavaScriptAlertPanel. Once the OK button has been clicked, it will call back the completionHandler in the webview and the rest of the javascript code will execute.

if (confirm('Do you want to confirm this?')) {
    //Do some code here when the user clicks ok
} else {
    //Do other code here when the user clicks cancel
}

As with the alert example, when javascript comes across the confirm method, it will call RunJavaScriptConfirmPanel. You can then show the dialog with the text passed through the message, along with an OK and Cancel button. Depending on the button clicked, the method will push either a true or false back to the webview and allow the rest of the javascript code to execute via the completion handler.

Upvotes: 4

Related Questions