1
votes

I'm trying to dynamically create and then destroy a component based on user interaction with a checkbox in QML. Check box on, create component. Check box off, destroy component. Creating the component works, but destroying it doesn't. The component is still there.

The documentation in QT docs here mention that the destroy method should work after creating a component. Any ideas what I could be doing wrong here? Code given below.

import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1

Rectangle {
    property var deficiencyType
    width: 600
    height: 800
    color:"white"
    CheckBox {
        id:checkbox
        text: "Check deficiency on/off"
        onClicked: {
            if (checked) {
                deficiencyType = Qt.createComponent("Form.qml")
                deficiencyType.createObject(columnRef)
            } else {
                deficiencyType.destroy()
                console.log(deficiencyType)
            }
        }
    }
    ColumnLayout {
        id:columnRef
        Layout.fillHeight: true
        Layout.fillWidth: true
        anchors {
            top: checkbox.bottom
            topMargin: 10
        }
    }
}
2

2 Answers

1
votes

As @Alaenix said, a Loader may work for you instead. But to directly answer your question, the problem with your destroy() is that you're destroying the component, not the object that you created. So changing this code:

                    deficiencyType = Qt.createComponent("Form.qml")
                    deficiencyType.createObject(columnRef)

to this:

                    var component = Qt.createComponent("Form.qml")
                    deficiencyType = component.createObject(columnRef)

should resolve your problem.

2
votes

For this usecase, you could use a Loader, like this :

import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1

Rectangle {
    width: 600
    height: 800
    color:"white"

    CheckBox {
        id: checkBox

        text: "Check deficiency on/off"
    }

    ColumnLayout {
        Layout.fillHeight: true
        Layout.fillWidth: true

        anchors {
            top: checkbox.bottom
            topMargin: 10
        }

        Loader {
            id: formLoader

            active: checkBox.checked
            source: "Form.qml"
        }
    }
}

There is several way to handle dynamic QML components. You should also check those ones :

EDIT:

To handle several items dynamic creation from a specific model, you should use a Repeater like this :

import QtQuick 2.7
import QtQuick.Layouts 2.14
import QtQuick.Controls 2.14

Rectangle {
    width: 600
    height: 900
    color:"white"

    property ListModel forms: ListModel {
        ListElement {
            formName: "Form one"
            formSource: "Form1.qml"
        }

        ListElement {
            formName: "Form two"
            formSource: "Form2.qml"
        }

        ListElement {
            formName: "Form three"
            formSource: "Form3.qml"
        }
    }

    RowLayout {
        anchors.fill: parent

        Repeater {
            model: forms

            delegate: Item {
                CheckBox {
                    id: checkBox

                    text: "Check " + modelData.formName + " on/off"
                }

                ColumnLayout {
                    Layout.fillHeight: true
                    Layout.fillWidth: true

                    anchors {
                        top: checkbox.bottom
                        topMargin: 10
                    }

                    Loader {
                        active: checkBox.checked
                        source: modelData.formSource
                    }
                }
            }
        }
    }
}