0

I'm trying to write my QML components in a modular fashion to be able to change the graphics on the fly but I'm struggling to nest them more than on a single level, here is an example:

import QtQuick 2.0
import QtGraphicalEffects 1.0

WindowFrame {
    id: this_item

    property Component body //this wont load the component
    property alias footer: footer_loader.sourceComponent //this gives an error -> Invalid alias reference. Unable to find id "footer_loader"

    property int footer_height: 70

    body: Item {
        id: body_component

        Loader {
            id: body_loader
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.right: parent.right
            height: parent.height-this_item.footer_height
            sourceComponent: this_item.body
        }

        Item {
            anchors.bottom: parent.bottom
            anchors.left: parent.left
            anchors.right: parent.right
            height: this_item.footer_height
            z: 2

            Rectangle {
                anchors.fill: parent
                color: Qt.rgba(0, 0, 0.5, 1)

                layer.enabled: true
                layer.effect: DropShadow {
                    transparentBorder: true
                    horizontalOffset: 0
                    verticalOffset: -8
                    radius: 8.0
                    samples: 17
                    color: Qt.rgba(0, 0, 0, 0.5)
                }
            }

            Loader {
                id: footer_loader
                anchors.fill: parent
            }
        }
    }
}

The goal is to build components with pre-defined spaces (like cards for example) and then load other elements inside these and did not found anything else other than using a loader, how sould it be done? is there a better approach to this?

Valentino Miori
  • 477
  • 1
  • 7
  • 16
  • 1
    Possible duplicate of [How should I start QML files?](https://stackoverflow.com/questions/48889031/how-should-i-start-qml-files) – Mohammad Kanan May 07 '18 at 14:31
  • Sorry but it is not quite like that one, this is a single window application and I already have my view router in place, the point is I cannot access a component used in a loader outside the component itself, this seems to me a bit buggy and not well documented, I would appreciate some help, maybe there is another way, I hope. – Valentino Miori May 07 '18 at 14:57
  • See my answer.. the first part gives you the correct syntax for your code.. I even gave you a better way to do the same thing that works well for nesting – mike510a May 10 '18 at 04:10
  • Yes, your answer was helpful but the card content both face and body (for example), is everytime different and I don't want to create each time a file for it there is no reason to. So I had to use: property alias body_item: body_loader.item property alias footer_item: footer_loader.item but then I can only acces the properties of root item of the loaded component, still searching for a better way although I don't think I'll find one i really like but thanks anyway – Valentino Miori May 10 '18 at 07:11
  • You can use `Qt.createQmlObject('import QtQuick 2.0; Card { imageSource: 'qrc://jack.png'}', parentItem, "ObjectName");` or something similar To dynamically create a card – mike510a May 11 '18 at 23:30

1 Answers1

1

YOu have to create Component Type Objects, not Item type

import QtQuick 2.0
import QtGraphicalEffects 1.0

WindowFrame {
    id: this_item

    property Component body //this wont load the component


     /*          
      * here is where you went wrong *  
      *  
      */
    body: Component {   // change Item to Component


        id: body_component


    }

     Card {
         id: myCard

     }
     Component.onCompleted {
        myCard.load_face("qrc:///jack.png")
     }
}

but the better answer is to create multiple QML files and dynamically create things like this

Card.qml

Item {
  id: card
  Rectangle {   
     width: 100
     height: 100

  }
  function load_face(imageSource) {
         var component = Qt.createComponent("CardFace.qml");
  if (component.status == Component.Ready)
      component.createObject(card, {"imageSource": imageSource, "y": 100});

  }
}

CardFace.qml

Item {
    id: face
    property var imageSource
    Image {
         source: face.imageSource
     }
}
mike510a
  • 2,102
  • 1
  • 11
  • 27