QWebChannel - js: Uncaught ReferenceError: qt is not defined



  • I am trying to migrate to QtWebEngine all my code that is using QWebKit.

    in my .cpp code:

    QWebChannel *channel = new QWebChannel(ui->webView_workouts->page());
    ui->webView_workouts->page()->setWebChannel(channel);
    channel->registerObject(QString("workoutObject"), this);
    

    In my webpage: (qwebchannel.js is loaded the header of the page)

    var workoutObject;
    new QWebChannel(qt.webChannelTransport, function (channel) {
      // now you retrieve your object
      workoutObject = channel.objects.workoutObject;
    });
    

    I am getting this error :
    js: Uncaught ReferenceError: qt is not defined
    When I try to use "workoutObject" in the js, since it is not loaded correctly I get:
    js: Uncaught TypeError: Cannot read property 'filterChanged' of undefined

    Any help appreciated, currently stuck to migrate with QWebEngine..



  • I tried to debug in the webpage and qt is always undefined for some reason?

    I am using latest Qt 5.7.0 on MSVC 2015

    var workoutObject;
    
    if (typeof qt != 'undefined') {
    	alert("Qt is OK!!");
    	new QWebChannel(qt.webChannelTransport, function (channel) {
            // now you retrieve your object
            workoutObject = channel.objects.workoutObject;
        });
    }
    else {
    	alert("Qt is not defined!");
    }
    


  • I copied the whole content of qwebchannel.js inside my page just before "new QWebChannel..." and I do not get the error on the Qtcreator console, but still qt is undefined (get the alert message on my webpage).

    Also to note that I try to set my channel after the page is loaded, and it get triggered 2 times? I only load the URL once. I read on other forums that reloading the page could stop the channel from working, but I am unable to make it work in the first place.

    ui->webView_workouts->load(QUrl(Environnement::getUrlWorkout()));
    connect(ui->webView_workouts->page(), SIGNAL(loadFinished(bool)), this, SLOT(connectToJs(bool)));
    
    void Main_WorkoutPage::connectToJs(bool result) {
    
        qDebug() << "connectToJs!" << result;
        if (result) {
            QWebChannel *channel = new QWebChannel(ui->webView_workouts->page());
            ui->webView_workouts->page()->setWebChannel(channel);
            channel->registerObject(QString("workoutObject"), this);
        }
    }
    

  • Lifetime Qt Champion

    Hi,

    I haven't played with QtWebChannel yet but did you get the QtWebChannel Standalone Example to run ? That might give you some hints to go further.

    Hope it helps


  • Moderators

    @maximus
    can you show how you include the qwebchannel.js into your page.
    Are you using a custom HTML page? or are you loading a page?


  • Moderators

    @maximus
    Here is a way to include the webchannel stuff without worrying anymore:

    QWebEngineProfile* profile = new QWebEngineProfile("MyWebChannelProfile", parent);
    
    QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js");
    if(  !webChannelJsFile.open(QIODevice::ReadOnly) )
    {
          qFatal( QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString()) );
    }
    else
    {
            QByteArray webChannelJs = webChannelJsFile.readAll();
            webChannelJs.append( 
                     "\n"
                     "new QWebChannel(qt.webChannelTransport, function(channel) {"
                     "     workoutObject = channel.objects.workoutObject;"
                     "});"
            );
    
            QWebEngineScript script;
                script.setSourceCode(webChannelJs);
                script.setName("qwebchannel.js");
                script.setWorldId(QWebEngineScript::MainWorld);
                script.setInjectionPoint(QWebEngineScript::DocumentCreation);
                script.setRunsOnSubFrames(false);
            profile->scripts()->insert(script);
        }
    

    Then make sure you create a QWebEnginePage with the profile on your view: new QWebEnginePage(profile,view)



  • hey @raven-worx, thanks for the reply

    I am using a custom html page that I control.
    The .js file is loaded this way:
    <script type="text/javascript" src="http://localhost/assets/js/qwebchannel.js"></script>
    I then have another <script> section at the end of my page that is creating a QWebChannel
    I can access the page source and click on the link fine to see the js file.

    Also note that I am using Designer to create my QWebEngineView so object is already instantiated in my .cpp

    I'll try loading it your way and post my result soon.
    Thanks



  • You are a lifesaver, it worked this way! Now to figure out how to strip and put this code generic because I use around 10 QWebEngineView :)

    QWebEngineProfile *profile = new QWebEngineProfile("MyWebChannelProfile", this);
    
        QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js");
        if(  !webChannelJsFile.open(QIODevice::ReadOnly) ) {
            qDebug() << QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString());
        }
        else {
            qDebug() << "OK webEngineProfile";
            QByteArray webChannelJs = webChannelJsFile.readAll();
            webChannelJs.append(
                        "\n"
                        "var workoutobject"
                        "\n"
                        "new QWebChannel(qt.webChannelTransport, function(channel) {"
                        "     workoutobject = channel.objects.workoutobject;"
                        "});"
                        );
    
            QWebEngineScript script;
            script.setSourceCode(webChannelJs);
            script.setName("qwebchannel.js");
            script.setWorldId(QWebEngineScript::MainWorld);
            script.setInjectionPoint(QWebEngineScript::DocumentCreation);
            script.setRunsOnSubFrames(false);
            profile->scripts()->insert(script);
        }
    
        QWebEnginePage *myPage = new QWebEnginePage(profile, ui->webView_workouts);
        ui->webView_workouts->setPage(myPage);
    
        QWebChannel *channel = new QWebChannel(myPage);
        ui->webView_workouts->page()->setWebChannel(channel);
        channel->registerObject("workoutobject", this);
    
        ui->webView_workouts->load(QUrl(Environnement::getUrlWorkout()));
    

    And now my .js page doesn't have anything related to Qt, really clean result.
    Thanks a lot
    Max



  • I am running into problem using profile->scripts()->insert(script);
    There is conflict with multiple scripts that I insert in my shared QWebEngineProfile.
    I use the same QWebEngineProfile on all my webpage in my application in order to keep cookie data, etc.

    So when I insert a new script, it overwrite the last one inserted and screw up my QWebChannel initialization
    Resulting in warning like "js: Uncaught ReferenceError: zoneObject is not defined"
    Trying to find a solution..
    script.setWorldId(QWebEngineScript::MainWorld); maybe set a unique worldID for each page but that doesnt seem to work now



  • Solution found, insert the script to the page instead of the profile

    void WorkoutCreator::createWebChannel() {
    
        QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
    
        QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js");
        if(  !webChannelJsFile.open(QIODevice::ReadOnly) ) {
            qDebug() << QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString());
        }
        else {
            qDebug() << "OK webEngineProfile";
            QByteArray webChannelJs = webChannelJsFile.readAll();
            webChannelJs.append(
                        "\n"
                        "var workoutCreator"
                        "\n"
                        "new QWebChannel(qt.webChannelTransport, function(channel) {"
                        "     workoutCreator = channel.objects.workoutCreator;"
                        "});"
                        "\n"
                        "function enableSaveButton(forceOff) {"
                        "if (forceOff) {$('#btn-save-workout').prop('disabled', true);return;}"
                        "var nameValue = $('#name-workout').val();"
                        "var planValue =   $('#plan-workout').val();"
                        "var creatorValue = $('#creator-workout').val();"
                        "if (nameValue.length > 0 && creatorValue.length > 0 && planValue.length > 0) {$('#btn-save-workout').prop('disabled', false);}"
                        "else {$('#btn-save-workout').prop('disabled', true);}"
                        "}"
                        );
    
            QWebEngineScript script;
            script.setSourceCode(webChannelJs);
            script.setName("qwebchannel.js");
            script.setWorldId(QWebEngineScript::MainWorld);
            script.setInjectionPoint(QWebEngineScript::DocumentCreation);
            script.setRunsOnSubFrames(false);
            //        profile->scripts()->insert(script);
    
            QWebEnginePage *myPage = new QWebEnginePage(profile, ui->webView_createWorkout);
            ui->webView_createWorkout->setPage(myPage);
            myPage->scripts().insert(script);
    
            QWebChannel *channel = new QWebChannel(myPage);
            ui->webView_createWorkout->page()->setWebChannel(channel);
            channel->registerObject("workoutCreator", this);
        }
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.