Search code examples
javascriptqmlloaderstackview

QML ReferenceError: <something> is not defined from Js function called from a qml file


Ok definitely not know what to do so I ask for help, I've looked everywhere and can not find solution. This is a long question involved the following files: sizeCalc.js, main.qml, MainForm.ui.qml, VentPrinc.qml and menuPrincElement.qml, the problem is this.

Inside the file MainForm.ui.qml have the structure of the main window which main.qml load and run from there the logic of the UI, the content of the files is this:

MainForm.ui.qml:

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
import "sizeCalc.js" 1.0 as CalcSize

Item {
    id: vent
    width: CalcSize.vW; height: CalcSize.vH
    property alias itemCont: itemCont
    property alias vent: vent
    property alias rootBarraUp: rootBarraUp

    Image {
        id: imgBgrnd
        source: "imgSources/background.jpg"
        sourceSize.height: parent.height
        fillMode: Image.PreserveAspectFit
        anchors.centerIn: parent
    }
    ColumnLayout {
        id: layoutPrinc
        anchors.fill: parent
        Rectangle {
            id: barraUpRef
            height: CalcSize.barrasPrnc; width: parent.width
            anchors.top: parent.top; color: "transparent"
            anchors.horizontalCenter: parent.horizontalCenter
        }
        Item {
            id: rootBarraUp; z:20
            width: parent.width; anchors.top: barraUpRef.top
            anchors.horizontalCenter: barraUpRef.horizontalCenter
        }
        Item {
            id:itemContGen
            anchors.top: barraUpRef.bottom; anchors.bottom: barraDown.top
            width: vent.width; anchors.horizontalCenter: parent.horizontalCenter
            Item {
                id: itemCont
                anchors.centerIn: parent
                height: CalcSize.espTrbHei; width: CalcSize.espTrbWid
            }
        }
        Rectangle {
            id: barraDown
            height: CalcSize.barrasPrnc; width: parent.width
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 0
            color: "white"; opacity: 0.3
        }
    }
    states: [
        State {
            name: "directorio"
            PropertyChanges {
                target: barraDown
                anchors.bottomMargin: -(height)
            }
        }
    ]
}

main.qml:

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import "sizeCalc.js" 1.0 as CalcSize

ApplicationWindow {
    title: qsTr("Hello World")
    width: 480
    height: 640
    visible: true
    MainForm {
        id: mainForm; anchors.fill: parent
        function chVent(arg){
            CalcSize.funcCambVent(arg)
        }
        itemCont.children: StackView {
            id: stackviewPrinc; anchors.fill: parent
            anchors.margins: CalcSize.espTrbDirecBordUp
            initialItem: compPrinc

            Component {
                id: compPrinc
                Loader {
                    id: loaderPrinc
                    source: "VentPrinc.qml"
                    Connections {
                        target: loaderPrinc.item.dirBoton
                        onClicked: CalcSize.funcCambVent(1)
                    }
                }
            }
            Component {
                id: compDir
                Loader {
                    id: loaderDir
                    source: "Directorio.qml"
                }
            }
            Component {
                id: comp3
                Loader {
                    id: loaderComp3
                }
            }
            Component {
                id: comp4
                Loader {
                    id: loaderComp4
                }
            }

            delegate: StackViewDelegate {
                function transitionFinished(properties){
                    properties.exitItem.opacity = 1
                }
                pushTransition: StackViewTransition {
                    PropertyAnimation {
                        target: enterItem
                        property: "opacity"
                        from: 0; to: 1
                    }
                    PropertyAnimation {
                        target: exitItem
                        property: "opacity"
                        from: 1; to: 0
                    }
                }
            }
        }
        rootBarraUp.children: Loader {
            id: barraUpLoader
            anchors.top: parent.top
            anchors.horizontalCenter: parent.horizontalCenter
            source: "menuPrincElement.qml"
            transitions: Transition {
                NumberAnimation {
                    properties: "height, width"
                    easing.type: Easing.InOutQuad
                }
            }
        }

        vent.transitions: [
            Transition {
                NumberAnimation {
                    target: barraDown; duration: 500
                    property: "anchors.bottomMargin"
                    easing.type: Easing.Linear
                }
            }
        ]
    }
}

VentPrinc.qml is loaded from a StackView within main.qml, This is the contents of the file:

import QtQuick 2.4
import QtQuick.Layouts 1.1
import "sizeCalc.js" 1.0 as CalcSize

Item {
    id: contenidoGen
    anchors.top: parent.bottom; anchors.bottom: parent.top
    anchors.horizontalCenter: parent.horizontalCenter
    width: CalcSize.espTrbWid
    property alias dirBoton: mouseAreaBotonDirPrinc
    property alias turBoton: mouseAreaBotonTurPrinc
    RowLayout {
        id: layoutBotonesPrinc
        anchors.centerIn: parent
        Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter

        Item {
            id: botonPrincDirectorio
            height: CalcSize.tamBotonesPrinc; width: height
            Image {
                id: imgBotonPrincDirectorio
                source: "imgSources/botones/directorioBotonPrinc.png"
                sourceSize.height: parent.height
                fillMode: Image.PreserveAspectFit
                anchors.centerIn: parent
            }
            MouseArea {
                id: mouseAreaBotonDirPrinc
                anchors.fill: parent
                /*onClicked: {
                    mainForm.chVent(1)
                }*/
            }
        }
        Item {
            id: botonPrincTurista
            height: CalcSize.tamBotonesPrinc; width: height
            Image {
                id: imgBotonPrincTurista
                source: "imgSources/botones/turistaBotonPrinc.png"
                sourceSize.height: parent.height
                fillMode: Image.PreserveAspectFit
                anchors.centerIn: parent
            }
            MouseArea {
                id: mouseAreaBotonTurPrinc
                anchors.fill: parent
            }
        }
    }
}

menuPrincElement.qml is loaded from a loader from main.qml (this element is a top bar of the UI), and this is the contents of the file:

import QtQuick 2.4
import QtQuick.Layouts 1.1
import "sizeCalc.js" 1.0 as CalcSize
Rectangle {
    property alias barraSup: barraUP
    id: barraUP
    height: CalcSize.barrasPrnc; width: CalcSize.vW
    color: "transparent"
    FontLoader { id: fontGent; source: "Aaargh.ttf" }
    function chTitulo(arg){
        switch(arg){
        case 0: tituloItemText.state = "stPrinc"; break;
        case 1: tituloItemText.state = "stDir"; break;
        case 2: tituloItemText.state = "stTur"; break;
        case 3: tituloItemText.state = "stConf"; break;
        }
    }

    Rectangle {
        id: backgroundMenuList; color: "white"; opacity: 0.0
        anchors.fill: parent
    }
    Item {
        id: contBarrUp
        height: CalcSize.barrasPrnc; width: parent.width
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        Rectangle {
            id: backgroundBarrUp; color: "white"; opacity: 0.3
            anchors.fill: parent
        }
        Item {
            id: menuItem
            width: CalcSize.tamBotonMenuPrinc
            height: CalcSize.tamBotonMenuPrinc
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: parent.left
            Image {
                id: menuItemImg
                source: "imgSources/botones/botonMenuPrinc.png"
                sourceSize.height: parent.height
                fillMode: Image.PreserveAspectFit
                anchors.centerIn: parent
            }
            MouseArea {
                id: menuItemMouseArea; anchors.fill: menuItem
                onClicked: {
                    if(barraUP.state == ""){
                        barraUP.state = "menuOn"
                    }else{
                        barraUP.state = ""
                    }
                }
            }
        }
        Text {
            id: tituloItemText; color: "white"
            //text: CalcSize.textoTitulo;
            anchors.centerIn: parent
            verticalAlignment: Text.AlignVCenter
            font { bold: true; pointSize: 16; family: fontGent.name }
            state: "stPrinc"
            states: [
                State {
                    name: "stPrinc"
                    PropertyChanges { target: tituloItemText; text: "App Turista" }
                },
                State {
                    name: "stDir"
                    PropertyChanges { target: tituloItemText; text: "Modo Directorio" }
                },
                State {
                    name: "stTur"
                    PropertyChanges { target: tituloItemText; text: "Modo Turista" }
                },
                State {
                    name: "stConf"
                    PropertyChanges { target: tituloItemText; text: "Configuración" }
                }
            ]
            Transition {
                PropertyAnimation {
                    target: tituloItemText
                    duration: 500; easing.type: Easing.InOutQuad
                }
            }
        }
    }
    Item {
        id: contOpcMenuGen; width: parent.width
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: contBarrUp.bottom; anchors.margins: 10
        anchors.bottom: barraUP.bottom; opacity: 0
        ListView {
            id: listaContMenuGen; anchors.fill: parent
            delegate: delegateElemMenuGen
            model: modelElemMenuGen
            spacing: CalcSize.tamBordeElemIntLista3
        }
    }
    Component {
        id: delegateElemMenuGen
        Rectangle {
            id: recPrinc; color: "transparent"
            anchors.margins: CalcSize.tamBordeElemIntLista2
            anchors.horizontalCenter: parent.horizontalCenter
            height: CalcSize.tamElemMenuPrincH
            width: CalcSize.espTrbWid
            Rectangle {
                id: backgroundRecPrinc; color: "white"; opacity: 0.8
                radius: CalcSize.tamBordeElemIntLista3
                anchors.fill: recPrinc
            }
            MouseArea {
                id: mouseAreaDelegateItem; anchors.fill: parent
                onClicked: {
                    CalcSize.funcCambVent(model.accion)
                    barraUP.state = ""
                }
            }
            Text {
                id: textoElem; color: "black"; text: model.titulo
                anchors.centerIn: parent
                font { bold: true; family: fontGent.name; pointSize: 12 }
            }
        }
    }
    ListModel {
        id: modelElemMenuGen
        ListElement { titulo: "Regresar al Inicio"; accion: 0 }
        ListElement { titulo: "Modo Directorio";    accion: 1 }
        ListElement { titulo: "Modo Turista";       accion: 2 }
        ListElement { titulo: "Configuración";      accion: 3 }
    }

    states: [
        State {
            name: "menuOn"
            PropertyChanges {
                target: tituloItemText; color: "#5a5a5a"
            }

            PropertyChanges {
                target: barraUP; height: CalcSize.tamElemMenuPrincExpand
            }
            PropertyChanges {
                target: contOpcMenuGen; opacity: 1
            }
            PropertyChanges {
                target: backgroundBarrUp; opacity: 0.75
            }
            PropertyChanges {
                target: backgroundMenuList; opacity: 0.7
            }
        }
    ]
    transitions: [
        Transition {
            from: ""; to: "menuOn"
            ParallelAnimation {
                NumberAnimation {
                    target: barraUP; properties: "height"
                    duration: 500; easing.type: Easing.InOutQuad
                }
                NumberAnimation {
                    target: backgroundBarrUp; property: "opacity"
                    duration: 500; easing.type: Easing.InOutQuad
                }
                ColorAnimation {
                    target: tituloItemText; duration: 500
                }
            }
            SequentialAnimation {
                NumberAnimation {
                    target: backgroundMenuList; property: "opacity"
                    duration: 250; easing.type: Easing.InOutQuad
                }
                NumberAnimation {
                    target: contOpcMenuGen; property: "opacity"
                    duration: 250; easing.type: Easing.InOutQuad
                }
            }
        },
        Transition {
            from: "menuOn"; to: ""
            SequentialAnimation {
                NumberAnimation {
                    target: contOpcMenuGen; property: "opacity"
                    duration: 250; easing.type: Easing.InOutQuad
                }
                NumberAnimation {
                    target: backgroundMenuList; property: "opacity"
                    duration: 250; easing.type: Easing.InOutQuad
                }
            }
            ParallelAnimation {
                NumberAnimation {
                    target: barraUP; properties: "height"
                    duration: 500; easing.type: Easing.InOutQuad
                }
                NumberAnimation {
                    targets: backgroundBarrUp; property: "opacity"
                    duration: 500; easing.type: Easing.InOutQuad
                }
                ColorAnimation {
                    target: tituloItemText; duration: 500
                }
            }
        }
    ]
}

And finally the sezeCalc.js file is simply a collection of functions and variables to calculate the size of the UI elements depending on the size of the window and this is the important contents of this file:

function funcCambVent(arg){
    switch(arg){
    case 0:
        barraSup.state = ""
        mainForm.state = ""
        barraSup.chTitulo(0)
        stackviewPrinc.push(compPrinc)
        break
    case 1:
        barraSup.state = ""
        mainForm.state = "directorio"
        barraSup.chTitulo(1)
        stackviewPrinc.push(compDir)
        break
    case 2:
        barraSup.state = ""
        mainForm.state = ""
        barraSup.chTitulo(2)
        stackviewPrinc.push(comp3)
        break
    case 3:
        barraSup.state = ""
        mainForm.state = ""
        barraSup.chTitulo(3)
        stackviewPrinc.push(comp4)
        break
    }
}

The problem is this, both VentPrinc.qml and menuPrincElement.qml have a MouseArea to call a function within sizeCalc.js which change the current "page" of StackView this in order to go to another "window" interface while retaining various UI elements, everything works perfectly if the function is called from the menuPrincElement.qml but to be called from VentPrinc.qml get the error "qrc: /sizeCalc.js: 16: ReferenceError: barraSup is not defined" I have tried everything I can to change the way in which the function is called but the error persists only when called from VentPrinc.qml, try connecting a signal from VentPrinc.qml to call a function in main.qml and that this function call the function sizeCalc.js also perform Connections from the Loader VentPrinc.qml located in the StackView of main.qml also I used property alias of the affected items from sizeCalc.js... well I do not know what else try to always get the same error "ReferenceError: barraSup is not defined" This error only happens when the signal is coming from VentPrinc.qml, please if anyone knows what I'm doing wrong I'd appreciate it very much, thank you very much for your attention and I hope your answers.

PS: I apologize for grammatical errors but this is a google translation, my grammar in English is not so good.

PD2: I left some parts of the code comented or unused of other solutions I have tried.


Solution

  • I found the solution, being honest I have no idea why this solution works, but it works, if anyone can explain this would be helpful for those it encounters this kind of problem. Change of function in the sizeCalc.js file:

    function funcCambVent(arg){
        switch(arg){
        case 0:
            barraUpLoader.item.state = ""
            mainForm.state = ""
            barraUpLoader.item.chTitulo(0)
            stackviewPrinc.push(compPrinc)
            break
        case 1:
            barraUpLoader.item.state = ""
            mainForm.state = "directorio"
            barraUpLoader.item.chTitulo(1)
            stackviewPrinc.push(compDir)
            break
        case 2:
            barraUpLoader.item.state = ""
            mainForm.state = ""
            barraUpLoader.item.chTitulo(2)
            stackviewPrinc.push(comp3)
            break
        case 3:
            barraUpLoader.item.state = ""
            mainForm.state = ""
            barraUpLoader.item.chTitulo(3)
            stackviewPrinc.push(comp4)
            break
        }
    }
    

    And VentPrinc.qml root element instead of Item I is replaced by Rectangle and rename the file to ventPrinc.qml, in this file is no longer necessary to connect in any way special function within sizeCalc.js, simply call the function directly, the final version of this file:

    import QtQuick 2.4
    import QtQuick.Layouts 1.1
    import "sizeCalc.js" 1.0 as CalcSize
    
    Rectangle {
        id: contenidoGen; color: "transparent"
        anchors.top: parent.bottom; anchors.bottom: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        width: CalcSize.espTrbWid
        property alias dirBoton: mouseAreaBotonDirPrinc
        property alias turBoton: mouseAreaBotonTurPrinc
        RowLayout {
            id: layoutBotonesPrinc
            anchors.centerIn: parent
            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
    
            Item {
                id: botonPrincDirectorio
                height: CalcSize.tamBotonesPrinc; width: height
                Image {
                    id: imgBotonPrincDirectorio
                    source: "imgSources/botones/directorioBotonPrinc.png"
                    sourceSize.height: parent.height
                    fillMode: Image.PreserveAspectFit
                    anchors.centerIn: parent
                }
                MouseArea {
                    id: mouseAreaBotonDirPrinc
                    anchors.fill: parent
                    onClicked: CalcSize.funcCambVent(1)
                }
            }
            Item {
                id: botonPrincTurista
                height: CalcSize.tamBotonesPrinc; width: height
                Image {
                    id: imgBotonPrincTurista
                    source: "imgSources/botones/turistaBotonPrinc.png"
                    sourceSize.height: parent.height
                    fillMode: Image.PreserveAspectFit
                    anchors.centerIn: parent
                }
                MouseArea {
                    id: mouseAreaBotonTurPrinc
                    anchors.fill: parent
                }
            }
        }
    }
    

    Besides this it is not necessary to use property alias dirBoton: mouseAreaBotonDirPrinc.

    The final StackView in main.qml is:

    itemCont.children: StackView {
                id: stackviewPrinc; anchors.fill: parent
                anchors.margins: CalcSize.espTrbDirecBordUp
                initialItem: compPrinc
    
                Component {
                    id: compPrinc
                    Loader { id: loaderPrinc; source: "ventPrinc.qml" }
                }
                Component {
                    id: compDir
                    Loader { id: loaderDir; source: "ventDir.qml" }
                }
                Component {
                    id: comp3
                    Loader { id: loaderTur }
                }
                Component {
                    id: comp4
                    Loader { id: loaderConf }
                }
            }