skip to Main Content

In Flutter I have a simple stateful widget that displays a website in fullscreen.
For that I’m using the webview_flutter plugin.
Here’s a simplified version of the widget where I removed irrelevant variables and functions. As an example the widget shows the Google website in fullscreen:

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

class WebViewScreen extends StatefulWidget {
  const WebViewScreen({
    Key? key,
  }) : super(key: key);

  @override
  State<WebViewScreen> createState() => _WebViewScreenState();
}

class _WebViewScreenState extends State<WebViewScreen> {
  @override
  void initState() {
    super.initState();
  }

  late WebViewController webViewController = WebViewController()
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..setBackgroundColor(const Color(0x00000000))
    ..setNavigationDelegate(
      NavigationDelegate(
        onProgress: (int progress) {},
        onPageStarted: (String url) {},
        onPageFinished: (String url) {},
        onWebResourceError: (WebResourceError error) {},
        onNavigationRequest: (NavigationRequest request) {
          return NavigationDecision.navigate;
        },
      ),
    )
    ..loadRequest(Uri.parse('https://www.google.com/'));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Expanded(
            child: WebViewWidget(
              controller: webViewController,
            ),
          ),
        ],
      ),
    );
  }
}

What I now want to do is to call a JavaScript function (for testing purposes let’s just make it alert('Hello World');) right when the webview loaded (onPageFinished).
How can I achieve this?

I asked ChatGPT-4 this exact question. Its answer was to add

webViewController.evaluateJavascript("alert('Hello World');");

within the onPageFinished method. So:

//...
//onPageFinished: (String url) {
   webViewController.evaluateJavascript("alert('Hello World');");
//},
//...

But this results in a problem:

The method 'evaluateJavascript' isn't defined for the type 'WebViewController'. Try correcting the name to the name of an existing method, or defining a method named 'evaluateJavascript'.

When I ask ChatGPT-4 about this problem it only provides answers which make no sense. I assume that has to do with the fact that ChatGPT has less knowledge about more recent developments.

I also found a similar question here but it doesn’t seem right because here a "WebView" widget is used instead of the "WebViewWidget" widget that I’m using.

2

Answers


  1. For this library, in order to call javascript functions, you may use webViewController.runJavaScriptReturningResult(String)

    Login or Signup to reply.
  2. This may help someone else, I noticed that the documentation may have a typo or it was updated recently, not sure, but here’s the typo:

    controller.runJavaScript
    

    Should be:

    controller.runJavascript
    

    In the following example on pub.dev for webview_flutter 4.1.0

      Future<void> _onShowUserAgent() {
        // Send a message with the user agent string to the Toaster JavaScript channel we registered
        // with the WebView.
        return webViewController.runJavaScript(
          'Toaster.postMessage("User Agent: " + navigator.userAgent);',
        );
      }
    
      Future<void> _onListCookies(BuildContext context) async {
        final String cookies = await webViewController
            .runJavaScriptReturningResult('document.cookie') as String;
        if (context.mounted) {
          ScaffoldMessenger.of(context).showSnackBar(SnackBar(
            content: Column(
              mainAxisAlignment: MainAxisAlignment.end,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                const Text('Cookies:'),
                _getCookieList(cookies),
              ],
            ),
          ));
        }
      }
    
      Future<void> _onAddToCache(BuildContext context) async {
        await webViewController.runJavaScript(
          'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";',
        );
        if (context.mounted) {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
            content: Text('Added a test entry to cache.'),
          ));
        }
      }
    
      Future<void> _onListCache() {
        return webViewController.runJavaScript('caches.keys()'
            // ignore: missing_whitespace_between_adjacent_strings
            '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))'
            '.then((caches) => Toaster.postMessage(caches))');
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search