16

How can I run Javascript in flutter_webview_plugin? I tried with this:

onPressed: () {
   flutterWebviewPlugin.evalJavascript('<script language="JavaScript" type="text/javascript">alert("Hello World")</script>');
},

But nothing happens.

I thought with flutterWebviewPlugin.evalJavascript it's possible to run Javascript in a Webview. Did I do something wrong?

Frank nike
  • 330
  • 5
  • 12
Art
  • 197
  • 1
  • 2
  • 14

6 Answers6

20
flutterWebviewPlugin.evalJavascript('<script language="JavaScript" type="text/javascript">alert("Hello World")</script>')

expects JavaScript, not HTML

<script language="JavaScript" type="text/javascript">alert("Hello World")</script>

is HTML.

Try

flutterWebviewPlugin.evalJavascript('alert("Hello World")')
JerryZhou
  • 4,566
  • 3
  • 37
  • 60
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I try it out but nothing happend. The Website is open in a WebviewScaffold Widget which contains an appBar with an IconButton maybe is the error here? – Art May 15 '18 at 12:33
  • Now I get SyntaxError in the Console. I/chromium(14510): [INFO:CONSOLE(1)] "Uncaught SyntaxError: missing ) after argument list", source: (1) – Art May 15 '18 at 12:50
  • Oh sorry it was a " to mutch. My fault. But it still doesn't work. I try it directly from my device not from the emulator. – Art May 15 '18 at 12:56
  • ok it works with printing in console or write in a textfield, but doesn't work with alert or window.open. maybe more don't know – Art May 15 '18 at 14:26
  • @Günter can I run this: view.loadUrl("javascript:(function() { " + "var head = document.getElementsByClassName('header')[0].style.display='none'; " + – Nick May 17 '19 at 06:19
  • not working too. there's an [github issue](https://github.com/flutter/flutter/issues/34853) been record about this. – JerryZhou Aug 18 '19 at 09:33
4

You can try my plugin flutter_inappwebview, which is a Flutter plugin that allows you to add inline WebViews or open an in-app browser window and has a lot of events, methods, and options to control WebViews.

To run some js, you can use:

  • Future<dynamic> evaluateJavascript({@required String source}): Evaluates JavaScript code into the WebView and returns the result of the evaluation.
  • Future<void> injectJavascriptFileFromUrl({@required String urlFile}): Injects an external JavaScript file into the WebView from a defined url.
  • Future<void> injectJavascriptFileFromAsset({@required String assetFilePath}): Injects a JavaScript file into the WebView from the flutter assets directory (see more here on how to load a file from the assets folder).

Full example:

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  runApp(new MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: InAppWebViewPage()
    );
  }
}

class InAppWebViewPage extends StatefulWidget {
  @override
  _InAppWebViewPageState createState() => new _InAppWebViewPageState();
}

class _InAppWebViewPageState extends State<InAppWebViewPage> {
  InAppWebViewController webView;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("InAppWebView")
        ),
        body: Container(
            child: Column(children: <Widget>[
              Expanded(
                child: Container(
                  child: InAppWebView(
                    initialUrl: "https://www.example.org/",
                    initialHeaders: {},
                    initialOptions: InAppWebViewWidgetOptions(
                      inAppWebViewOptions: InAppWebViewOptions(
                        debuggingEnabled: true,
                      ),
                    ),
                    onWebViewCreated: (InAppWebViewController controller) {
                      webView = controller;
                    },
                    onLoadStart: (InAppWebViewController controller, String url) {

                    },
                    onLoadStop: (InAppWebViewController controller, String url) async {
                      int result1 = await controller.evaluateJavascript(source: "10 + 20;");
                      print(result1); // 30

                      String result2 = await controller.evaluateJavascript(source: """
                        var firstname = "Foo";
                        var lastname = "Bar";
                        firstname + " " + lastname;
                      """);
                      print(result2); // Foo Bar

                      // inject javascript file from an url
                      await controller.injectJavascriptFileFromUrl(urlFile: "https://code.jquery.com/jquery-3.3.1.min.js");
                      // wait for jquery to be loaded
                      await Future.delayed(Duration(milliseconds: 1000));
                      String result3 = await controller.evaluateJavascript(source: "\$('body').html();");
                      print(result3); // prints the body html

                      // inject javascript file from assets folder
                      await controller.injectJavascriptFileFromAsset(assetFilePath: "assets/myJavascriptFile.js");
                    },
                  ),
                ),
              ),
            ]))
    );
  }
}
Lorenzo Pichilli
  • 2,896
  • 1
  • 27
  • 50
  • How do you get an element clicked in this plugin? How can I check if the user has pressed on a certain element on the page? – KylianMbappe Jun 12 '20 at 10:04
  • Hi @Lorenzo Pichilli, I'm trying to use your example with Stripe. So my JS string is filled in with " var stripe = Stripe(\'$pubStripeKey\'); stripe.redirectToCheckout({ sessionId: '${result['data']}' }).then(function (result) { result.error.message = 'Error' }); ". But for whatever reason I can't get this to seem to evaluate. It returns "null" on the call to await controller.evaluateJavascript(). But also no errors? Any ideas? – Eradicatore Apr 20 '21 at 16:08
  • Maybe it's an issue with the redirection? but I tried making an error like changing Stripe() to Stripey() and didn't see errors either. It's like the JS I feed the webview just isn't evaluated. – Eradicatore Apr 20 '21 at 16:22
2

This is how your Webview widget should look like

WebView(
    initialUrl: 'http://<domain>',
    javascriptMode: JavascriptMode.unrestricted,
    onWebViewCreated: (WebViewController webViewController) {
      webViewController.evaluateJavascript(
          'alert('hello from flutter)');
    }

Make use of webViewController anywhere in your code

Pranay Dutta
  • 2,483
  • 2
  • 30
  • 42
1

Well, nothing happened because flutter webview does not support javascript alert function. Try writing a javascript function that changes the value of the innerText of an HTML element and then call the function using .evalJavascript to see the result.

alexdabest
  • 61
  • 1
  • 3
1

My best way with onPressed function using the webview_flutter. Use 'runJavascript' or evaluateJavascript or 'runJavascriptReturningResult':

import 'package:flutter/material.dart';
import 'dart:io';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter/services.dart';


dynamic ctrl; // Created here to keep working with Hot Reload

void main() {
  runApp(
    MaterialApp(
      home: WebViewExample(),
    ),
  );
}

class WebViewExample extends StatefulWidget {
  @override
  WebViewExampleState createState() => WebViewExampleState();
}

class WebViewExampleState extends State<WebViewExample> {
  @override
  void initState() {

    super.initState();

    // Enable virtual display.
    if (Platform.isAndroid) WebView.platform = AndroidWebView();

  }


  @override
  Widget build(BuildContext context) {

    void runJS(command) async {
      ctrl.runJavascript(command);

      // If you get any result
      // dynamic r = await ctrl.runJavascriptReturningResult(command);
      // print(r);
    }

    return Scaffold(
      appBar: AppBar(
          title: Container(
        child: ElevatedButton(
          onPressed: () => {
            runJS('alert("Hello: Button Clicked! "+new Date())')
          },
          child: const Text('Click on the button'),
        ),
      )),
      body: WebView(
        initialUrl:
            'https://www.google.com',

        debuggingEnabled: true,

        onWebViewCreated: (WebViewController webViewController) {
         
          ctrl = webViewController;
         
          ctrl.runJavascript('alert("Hello: created!")');
          // ctrl.evaluateJavascript('alert("Hello: created!")');
          // ctrl.runJavascriptReturningResult('alert("Hello: created!")');
        },

        onPageStarted: (String url) async {
          // ctrl.runJavascript('alert("Hello: started!")');
          // ctrl.evaluateJavascript('alert("Hello: started!")');
          // ctrl.runJavascriptReturningResult('alert("Hello: started!")');
        },

        onPageFinished: (String url) async {
          // ctrl.runJavascript('alert("Hello: finished!")');
          // ctrl.evaluateJavascript('alert("Hello: finished!")');
          // ctrl.runJavascriptReturningResult('alert("Hello: finished!")');
        },
      ),
    );
  }
}
Cesar Devesa
  • 990
  • 6
  • 14
0

I have debug with iOS part of flutter_webview_plugin.

For iOS part

Found it's related to iOS native part iOS WKWebView not showing javascript alert() dialog .

Good example of implement code are at gist.

I have create a fix for this.

Temp solution

You can use

flutter_webview_plugin:
    git:
      ref: "dev/fix_alert_not_work_in_webview"
      url: "https://github.com/jerryzhoujw/flutter_webview_plugin"
      source: git

this as temp in pubspec.yaml before merge PR.

JerryZhou
  • 4,566
  • 3
  • 37
  • 60