# Splitting qml file into several files

**URL:** <https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553>\
**Category:** General Usage\
**Tags:** question, qml\
**Created:** [February 10, 2026, 11:56am UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553 "2026-02-10T11:56:00Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![HVinther](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hvinther/32/220446_2.png) [@HVinther](https://discourse.julialang.org/u/HVinther)\
**Post date:** [February 10, 2026, 11:56am UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/1 "2026-02-10T11:56:00Z")

</div>

Following [https://stackoverflow.com/questions/45652525/qml-filling-menu-with-model-items](https://stackoverflow.com/questions/45652525/qml-filling-menu-with-model-items) I made a menu that behaves similarly to standard Makie menu. To make my project more manageable I am trying to split my files into smaller files. Following [Breaking up QML into different files. [solved] | Qt Forum](https://forum.qt.io/topic/28438/breaking-up-qml-into-different-files-solved) I put my menu into a seperate qml file and imported the directory. While I am able to import the separate qml file into my main file and use the component, the imported menu does not behave as the one written out in the `main.qml` file - more precisely the new menu is empty, in the sense that it has no menu items. The text on the button does appear correctly though.

Any thoughts?

File structure:

```julia-auto
├── main.jl
├── main.qml
└── qml_components
    └── SensorMenu.qml

```

Main julia file, `main.jl`:

```julia
#main.jl
using QML, Observables
mutable struct menu_item
    text::String
end

items = ["x", "y", "z"]
items = [menu_item(item) for item in items]
item_model = JuliaItemModel(items)

current_item = Observable("x")

loadqml(
    "main.qml",
    observables=JuliaPropertyMap(
        "current_item" => current_item
    ),
    item_model = item_model
)

exec()

```

main qml file, `main.qml`:

```qml
//main.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import jlqml
import "qml_components" as Comp

ApplicationWindow {
    id: root
    title: "menus"
    visible: true
    width: 640
    height: 488
    onClosing: Qt.quit()

    RowLayout {
        // menu which works as expected, when called in the main qml file
        Button {
            id: fileButton
            text: observables.current_item
            onClicked: menu.open()

            Menu {
                id: menu
                y: fileButton.height
                visible: true
                Instantiator {
                    id: item_instatiator
                    model: item_model
                    delegate: MenuItem {
                        text: model.text
                        onTriggered: {
                            observables.current_item = model.text;
                        }
                    }

                    onObjectAdded: menu.insertItem(index, object)
                    onObjectRemoved: menu.removeItem(object)
                }
            }
        }

        // same menu but imported from another qml-file
        // expected to work as the first one, though is empty
        Comp.SensorMenu {
            text: observables.current_item
            lm: item_model
        }
    }
}

```

extra qml for holding the custom menu, `SensorMenu.qml`:

```qml
//SensorMenu.qml
import QtQuick
import QtQuick.Controls
import jlqml

Button {
    id: root
    property ListModel lm

    onClicked: menu.open()

    Menu {
        id: menu
        y: parent.height
        visible: true
        Instantiator {
            id: menu_instantiator
            model: root.lm
            delegate: MenuItem {
                text: model.text
                onTriggered: {
                    root.text = model.text;
                }
            }

            onObjectAdded: menu.insertItem(index, object)
            onObjectRemoved: menu.removeItem(object)
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![HVinther](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hvinther/32/220446_2.png) [@HVinther](https://discourse.julialang.org/u/HVinther)\
**Post date:** [February 10, 2026, 2:05pm UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/2 "2026-02-10T14:05:13Z")

</div>

So the example ends up looking as shown in the screencapture below:

---

<div class="post-metadata">

**Author:** ![HVinther](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hvinther/32/220446_2.png) [@HVinther](https://discourse.julialang.org/u/HVinther)\
**Post date:** [February 10, 2026, 2:32pm UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/3 "2026-02-10T14:32:44Z")

</div>

After inspecting the Qt docs [QML Object Attributes | Qt Qml | Qt 6.10.2](https://doc.qt.io/qt-6/qtqml-syntax-objectattributes.html) i managed to solve part of the issue by using a property alias in the SensorMenu definition as seen below.

```qml
//SensorMenu
import QtQuick
import QtQuick.Controls

Button {
    id: root
    property alias model: menu_instantiator.model

    onClicked: menu.open()

    Menu {
        id: menu
        y: parent.height
        visible: true
        Instantiator {
            id: menu_instantiator
            //model: root.lm
            delegate: MenuItem {
                text: model.text
                onTriggered: {
                    root.text = model.text;
                }
            }

            onObjectAdded: menu.insertItem(index, object)
            onObjectRemoved: menu.removeItem(object)
        }
    }
}

```

Now since i have renamed the property to `model` instead of `lm` this has to be changed in the `main.qml` file as well.

Now, while the menu does populate as expected, the text update seems to disconnect the text from the observable. See the video below, where the button texts are synced while changing only the left button, but using the right button seems to disconnect the two.

---

<div class="post-metadata">

**Author:** ![HVinther](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hvinther/32/220446_2.png) [@HVinther](https://discourse.julialang.org/u/HVinther)\
**Post date:** [February 10, 2026, 2:50pm UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/4 "2026-02-10T14:50:18Z")

</div>

Digging a bit more around the Qt docs, [Signal and Handler Event System | Qt Qml | Qt 6.10.2](https://doc.qt.io/qt-6/qtqml-syntax-signals.html#property-change-signal-handlers), I did get the text update to update the observable as well using signals.

```qml
//SensorMenu
import QtQuick
import QtQuick.Controls

Button {
    id: root
    property string current_text
    property alias model: menu_instantiator.model

    signal changed(text: string)
    text: current_text
    onClicked: menu.open()

    Menu {
        id: menu
        y: parent.height
        visible: true
        Instantiator {
            id: menu_instantiator
            //model: root.lm
            delegate: MenuItem {
                text: model.text
                onTriggered: {
                    current_text = model.text;
                    root.changed(current_text);
                }
            }

            onObjectAdded: menu.insertItem(index, object)
            onObjectRemoved: menu.removeItem(object)
        }
    }
}

```

```qml
//main.qml
...
        Comp.SensorMenu {
            current_text: observables.current_item
            model: item_model

            onChanged: current_text => {
                observables.current_item = current_text;
            }
        }
 ...

```

---

<div class="post-metadata">

**Author:** ![HVinther](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hvinther/32/220446_2.png) [@HVinther](https://discourse.julialang.org/u/HVinther)\
**Post date:** [February 10, 2026, 3:10pm UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/5 "2026-02-10T15:10:18Z")

</div>

If anyone is interested I’ve made a quick repository to host the final state of the code in this post.

> **[discourse.julialang-Splitting\_qml\_file\_into\_several\_files](https://codeberg.org/hansvintherrossen/discourse.julialang-Splitting_qml_file_into_several_files)**
>
> This repository holds my solution to my question on \[discourse.julialang\](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553).

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [February 10, 2026, 8:31pm UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/6 "2026-02-10T20:31:23Z")

</div>

Was there any problem in QML.jl that made this behave in an unexpected way, or was this a generic QML issue?

---

<div class="post-metadata">

**Author:** ![HVinther](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hvinther/32/220446_2.png) [@HVinther](https://discourse.julialang.org/u/HVinther)\
**Post date:** [February 11, 2026, 12:03pm UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/7 "2026-02-11T12:03:10Z")

</div>

I don’t think I’m experienced enough with qml or QML.jl to correctly answer this question.

---

<div class="post-metadata">

**Author:** ![HVinther](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hvinther/32/220446_2.png) [@HVinther](https://discourse.julialang.org/u/HVinther)\
**Post date:** [February 18, 2026, 9:37am UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/8 "2026-02-18T09:37:13Z")

</div>

Okay… My troubles are not over yet, as I am still struggling in how to split components, that act on components from julia, in to smaller files. Is it possible to also have the logic in the smaller files? ie. updating observables or juliaItemModels with logic in the smaller qml files instead of writing signals, that is handled in the main.qml file.

Perhaps, what I am asking. Could I implement the button above in a seperate qml file. Then import it and simply pass my observable to property, and have the button update the observable, without further logic in the main.qml file?

---

<div class="post-metadata">

**Author:** ![Janis\_Erdmanis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janis_erdmanis/32/10869_2.png) [@Janis\_Erdmanis](https://discourse.julialang.org/u/Janis_Erdmanis)\
**Post date:** [February 18, 2026, 10:17am UTC](https://discourse.julialang.org/t/splitting-qml-file-into-several-files/135553/9 "2026-02-18T10:17:57Z")

</div>

From my experience, what works well is to design the interaction with Julia so that the same QML application can run in mockup mode and with a Julia backend. I have found that a generic `App.qml` component, driven by a prototype model like [Prototype.qml](https://github.com/PeaceFounder/PeaceFounderClient/blob/main/qml/Prototype.qml) or, once the UI is fixed, by [Bridge.qml](https://github.com/PeaceFounder/PeaceFounderClient/blob/main/qml/Bridge.qml), works best from a code organisation perspective.

Nevertheless, I have only made one QML application and am therefore not an expert on the matter, so take my ramblings with a grain of salt. Perhaps you may develop a better approach.
