Why do I get this error in the QML code: ReferenceError: m_jsonDocStr is not defined
,
even if m_jsonDocStr
is specified here in the C++ code:
Q_PROPERTY(QString m_jsonDocStr READ jsonDocToStr WRITE setJsonDocStr NOTIFY jsonDocStrChanged)
And why the QmlLink.open() C++ function is not opened from QML? (neither as a normal member function nor as a slot)
TypeError: Property 'open' of object [object Object] is not a function
Next, with the "<–" comment I point to the critical lines of the code, with the error messages I get.
This is the QML file:
/** Main.qml */
import QtCore
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Dialogs
import QtQuick.Layouts
import main
ApplicationWindow {
id: window
width: 640
height: 480
visible: true
title: qsTr("Data input widget")
property string dataFilename: ""
property string dataFile: ""
menuBar: MenuBar {
Menu {
title: qsTr("&File")
Action {
text: qsTr("&Open...")
onTriggered: fileDialog.open()
}
}
}
ScrollView {
id: fileContents
anchors.fill: parent
property string dataFile: m_jsonDocStr // <-- ReferenceError: m_jsonDocStr is not defined
TextArea {
text: "File: " + dataFilename + "n" + dataFile + "nLength: " + dataFile.length
}
}
FileDialog {
id: fileDialog
title: "Open data file"
nameFilters: ["JSON files (*.json)"]
onAccepted: {
dataFilename = selectedFile
console.log("Open file: " + dataFilename)
QmlLink.open(dataFilename) // <-- TypeError: Property 'open' of object [object Object] is not a function
console.log("File contents: " + m_jsonDocStr)
}
onRejected: {
console.log("No file selected.")
}
}
}
Here is the header file:
/** QmlLink.hpp */
#ifndef QMLLINK_HPP
#define QMLLINK_HPP
#include <QObject>
#include <QJsonDocument>
#include <QtQml/qqmlregistration.h>
class QmlLink : public QObject
{
Q_OBJECT
Q_PROPERTY(QJsonDocument m_jsonDoc READ jsonDoc WRITE setJsonDoc NOTIFY jsonDocChanged)
Q_PROPERTY(QString m_jsonDocStr READ jsonDocToStr WRITE setJsonDocStr NOTIFY jsonDocStrChanged)
QML_ELEMENT
public:
explicit QmlLink(QObject *parent = nullptr);
public slots:
QJsonDocument jsonDoc() const { return m_jsonDoc; }
void setJsonDoc(const QJsonDocument &jsonDoc) { m_jsonDoc = jsonDoc; }
QString jsonDocToStr() const { return m_jsonDoc.toJson(); }
void setJsonDocStr(const QString &jsonDoc) { m_jsonDoc = QJsonDocument::fromJson(jsonDoc.toUtf8()); }
signals:
void jsonDocChanged();
void jsonDocStrChanged();
public slots:
void menuOpen();
int open(QString filePath);
private:
QJsonDocument m_jsonDoc;
QString m_jsonDocStr;
QString m_jsonFileName = "default.json";
};
#endif // QMLLINK_HPP
This is the implementation file:
/** QmlLink.cpp */
#include "QmlLink.hpp"
#include <iostream>
#include <QDebug>
#include <QFile>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickView>
QmlLink::QmlLink(QObject *parent) : QObject{parent} {}
void QmlLink::menuOpen() {
open(m_jsonFileName);
}
int QmlLink::open(QString filePath)
{
m_jsonFileName = filePath;
QUrl url(filePath);
QFile jsonFile;
jsonFile.setFileName(url.toLocalFile());
if(jsonFile.open(QIODevice::ReadOnly) == false) {
return -1;
}
const QByteArray data = jsonFile.readAll();
m_jsonDoc = QJsonDocument::fromJson(data);
const QString strDoc(m_jsonDoc.toJson(QJsonDocument::Compact));
std::cout << "Data file contents: " << strDoc.toStdString() << std::endl;
return 0;
}
This is a classic main() function:
/** main.cpp */
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "QmlLink.hpp"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QmlLink qmlLink;
QQmlApplicationEngine engine;
const QUrl url(u"qrc:/main/Main.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
&app, []() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
engine.load(url);
QQmlContext *rootContext = engine.rootContext();
rootContext->setContextProperty("QmlLink", &qmlLink);
return app.exec();
}
This is the trivial JSON file:
{
"Array": [
true,
999,
"string"
],
"Key": "Value",
"null": null
}
Tools versions:
- Qt 6.5
- OS: Linux
- gcc 13.1
- clang 15
2
Answers
You should set the context property before loading the url :
and fix the
Main.qml
:I think you can’t pass
QJsonDocument
from C++ to QML.As you mentioned you will get an "Unable to assign [undefined] to QString" error.
But My Idea is to pass QByteArray.
Here is my example:
In main.cpp:
in Main.qml
This is my result: