简体   繁体   中英

How to use Flutter webview evaluateJavascript?

I try to use webview evaluateJavascript and got error. WebView Controller has 2 function; evaluateJavascript , and loadUrl . I tested both in onPageFinished: (url){} , so I can initialise my javascript code. Documentation is not clear. But the error tells me something missing pr not implemented in webview plugin. I am trying to load page and initialising some basic javascript so I can hide some part of the page.

How to use Flutter webview evaluateJavascript?

Error:

Syncing files to device iPhone X...
flutter: Page finished loading: https://stackoverflow.com/
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: PlatformException(evaluateJavaScript_failed, Failed evaluating JavaScript, JavaScript string was: 'javascript:(function() { var head = document.getElementsByClassName('top-bar js-top-bar top-bar__network _fixed')[0].style.display='none'; })()'
Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=1, WKJavaScriptExceptionMessage=TypeError: undefined is not an object (evaluating 'document.getElementsByClassName('top-bar js-top-bar top-bar__network _fixed')[0].style'), WKJavaScriptExceptionColumnNumber=117, WKJavaScriptExceptionSourceURL=https://stackoverflow.com/, NSLocalizedDescription=A JavaScript exception occurred})
#0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:564:7)
#1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:33)
<asynchronous suspension>
#2      WebViewController.evaluateJavascript (package:web<…>
Application finished.

Code:

    class _WebViewExampleState extends State<WebViewExample> {
    WebViewController _myController;
      bool _loadedPage = false;

      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        setState(() {
          _loadedPage = false;
        });
      }


      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.green,
            title: const Text(
              ’Stackoverflow’,
              style: TextStyle(fontSize: 14),
            ),

          ),
          body: Builder(builder: (BuildContext context) {
            return new Stack(
              children: <Widget>[
                new WebView(
                  initialUrl: 'https://stackoverflow.com',
                  javascriptMode: JavascriptMode.unrestricted,
                  onWebViewCreated: (controller){
                    _myController = controller;
                  },
                  javascriptChannels: <JavascriptChannel>[
                    _toasterJavascriptChannel(context),
                  ].toSet(),
                  onPageFinished: (url){
                    print('Page finished loading: $url');

                    _myController.evaluateJavascript("javascript:(function() { " +
                        "var head = document.getElementsByClassName('top-bar js-top-bar top-bar__network _fixed')[0].style.display='none'; " +
                        "})()");

/*
                _myController.loadUrl("javascript:(function() { " +
                    "var head = document.getElementsByClassName('top-bar js-top-bar top-bar__network _fixed')[0].style.display='none'; " +
                    "})()");
*/

                    setState(() {
                      _loadedPage = true;
                    });
                  },
                ),
                _loadedPage == false
                    ? new Center(
                        child: new CircularProgressIndicator(
                            backgroundColor: Colors.green),
                      )
                    : new Container(),
              ],
            );
          }),

        );
      }

      JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
        return JavascriptChannel(
            name: 'Toaster',
            onMessageReceived: (JavascriptMessage message) {
              Scaffold.of(context).showSnackBar(
                SnackBar(content: Text(message.message)),
              );
            });
      }

    }

You are using it correctly - though you don't need to wrap it inside

javascript:(function() { }

Anyway, this is the important part of the error message:

TypeError: undefined is not an object

This merely means the object for which you're trying to modify the style attribute doesn't exist.

If you try the following code

_myController.evaluateJavascript("console.log(document.documentElement.innerHTML);");
                  setState(() {
              _loadedPage = true;
            });

and take a look at the debug console, you'll notice that this code - which should return the complete HTML for the stackoverflow website - just returns a little bit and not enough to reach the header element which uses the class top-bar js-top-bar top-bar__network _fixed .

使用document.getElementsByClassName('someclassname')[0]对我有用。

All the answers are outdated now, and evaluateJavascript no longer existed in the package. It's now call runJavascript ; If you don't need value return from your javascript, otherwise use runJavascriptReturningResult .

You can see an example here

Use controller.evaluateJavascript to edit on webview javascript, available in in_app_webview packages.

Notes that controller.evaluateJavascript need to write inside onLoadStop() functions. Inside the code where your WebView is finished loaded.

Example:

String Username = 'User';
String Password = '123';
InAppWebView(
 ...
onLoadStop: (controller, url) async{
            pullToRefreshController.endRefreshing();
            controller.evaluateJavascript(
                source: '''
                document.getElementById('uname').value = "$Username"; //Autofill in username field
                document.getElementById('pwd').value = "$Password"; //Autofill in password field
                var z = document.getElementById('submitBtn').click(); //Autoclick function
                '''
            );

            setState(() {
              this.url = url.toString();
              urlController.text = this.url;
            });

          },
 ...
)//InAppWebView

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM