Structure of a QML Document | Qt Qml | Qt 6.10.3
Description: Description of the structure of QML documents

- Qt 6.10
- Qt Qml
- The QML Reference
- QML Documents
- Structure of a QML Document
- Qt 6.10.3 Reference Documentation

QML Documents ◦ Defining Object Types in QML

# Structure of a QML Document

A QML document is a self contained piece of QML source code that consists of three parts:

- An optional list of pragmas
- Its import statements
- A single root object declaration

By convention, a single empty line separates the imports from the object hierarchy definition.

QML documents are always encoded in UTF-8 format.

## Pragmas

Pragmas are instructions to the QML engine itself that can be used to specify certain characteristics of objects in the current file or to modify how the engine interprets code. The following pragmas are exaplained in details below.

- `Singleton`
- `ListPropertyAssignBehavior`
- `ComponentBehavior`
- `FunctionSignatureBehavior`
- `NativeMethodBehavior`
- `ValueTypeBehavior`
- `Translator`

### Singleton

`pragma Singleton` declares the component defined in the QML document as singleton. Singletons are created only once per QML engine. In order to use a QML-declared singleton you also have to register it with its module. See qt_target_qml_sources for how to do this with CMake.

### ListPropertyAssignBehavior

With this pragma you can define how assignments to list properties shall be handled in components defined in the QML document. By default, assigning to a list property appends to the list. You can explicitly request this behavior using the value `Append`. Alternatively, you can request the contents of list properties to always be replaced using `Replace`, or replaced if the property is not the default property using `ReplaceIfNotDefault`.

Consider a base type in a document Base.qml:

     pragma ListPropertyAssignBehavior: ReplaceIfNotDefault
     import QtQuick

     Item {
         objectName: "outer"

         default property list<Item> d: [
             Item { objectName: "inner" }
         ]

         property list<Item> notDefault: [
             Item { objectName: "one" }
         ]
     }

Then, if you derive from Base and modify its list properties, the ListPropertyAssignBehavior takes effect. In this case:

     Base {
         // The new item is appended to the list even though you're assigning.
         // The (default) property "d" now contains "inner" and "inner2".
         d: [
             Item { objectName: "inner2" }
         ]

         // The list is replaced by the list given here.
         // The (non-default) property "notDefault" now contains only "two".
         notDefault: [
             Item { objectName: "two" }
         ]
     }

If no `ListPropertyAssignBehavior` is given or if `Append` is given, the "two" object will be appended to the `notDefault` property instead, resulting in a list that contains both, "one" and "two".

If `Replace` is given, the contents of the default property "d" will also be replaced, resulting in a list that contains only "inner2".

Note: The same declaration can also be given for C++-defined types, by adding the QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND, QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE, and QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT macros to the class declaration. For example:

     class MyType : public QObject
     {
         Q_OBJECT
         QML_ELEMENT
         QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE

         Q_PROPERTY(QQmlListProperty<QObject> a READ a)
         [...]
     };

### ComponentBehavior

You may have multiple components defined in the same QML file. The root scope of the QML file is a component, and you may additionally have elements of type QQmlComponent, explicitly or implicitly created as properties, or inline components. Those components are nested. Each of the inner components is within one specific outer component. Most of the time, IDs defined in an outer component are accessible within all its nested inner components. You can, however, create elements from a component in any a different context, with different IDs available. Doing so breaks the assumption that outer IDs are available. Therefore, the engine and the QML tooling cannot generally know in advance what type, if any, such IDs will resolve to at run time.

With the ComponentBehavior pragma you can restrict all inner components defined in a file to only create objects within their original context. If a component is bound to its context, you can safely use IDs from outer components in the same file within the component. QML tooling will then assume the outer IDs with their specific types to be available.

In order to bind the components to their context specify the `Bound` argument:

     pragma ComponentBehavior: Bound

This implies that, in case of name clashes, IDs defined outside a bound component override local properties of objects created from the component. Otherwise it wouldn't actually be safe to use the IDs since later versions of a module might add more properties to the component. If the component is not bound, local properties override IDs defined outside the component, but not IDs defined inside the component.

The example below prints the r property of the ListView object with the id color, not the r property of the rectangle's color.

     pragma ComponentBehavior: Bound
     import QtQuick

     ListView {
      id: color
      property int r: 12
      model: 1

      delegate: Rectangle {
       Component.onCompleted: console.log(color.r)
      }
     }

The default value of `ComponentBehavior` is `Unbound`. You can also specify it explicitly. In a future version of Qt the default will change to `Bound`.

Delegate components bound to their context don't receive their own private contexts on instantiation. This means that model data can only be passed via required properties in this case. Passing model data via context properties will not work. This concerns delegates to e.g. Instantiator, Repeater, ListView, TableView, GridView, TreeView and in general anything that uses DelegateModel internally.

For example, the following will not work:

     pragma ComponentBehavior: Bound
     import QtQuick

     ListView {
      delegate: Rectangle {
          color: model.myColor
      }
     }

The `delegate` property of ListView is a component. Therefore, a Component is implicitly created around the Rectangle here. That component is bound to its context. It doesn't receive the context property `model` provided by ListView. To make it work, you'd have to write it this way:

     pragma ComponentBehavior: Bound
     import QtQuick

     ListView {
      delegate: Rectangle {
          required property color myColor
          color: myColor
      }
     }

You can nest components in a QML file. The pragma holds for all components in the file, no matter how deeply nested.

### FunctionSignatureBehavior

With this pragma you can change the way type annotations on functions are handled. Since Qt 6.7 type annotations are enforced when calling functions. Before, only the QML script compiler enforced the type annotations. The interpreter and JIT compiler ignored them. Always enforcing the type annotations is a behavior change in comparison to earlier versions since you could call functions with mismatched arguments before.

Specifying `Ignored` as value makes the QML engine and the QML script compiler ignore any type annotations and therefore restores the pre-6.7 behavior of the interpreter and JIT. As a result less code is compiled to C++ ahead of time, and more code has to be interpreted or JIT-compiled.

Specifying `Enforced` as value explicitly states the default: Type annotations are always enforced.

### NativeMethodBehavior

Calling C++ methods with `this` objects different from the one they were retrieved from is broken, due to historical reasons. The original object is used as `this` object. You can allow the given `this` object to be used by setting `pragma NativeMethodBehavior: AcceptThisObject`. Specifying `RejectThisObject` keeps the historical behavior.

An example of this can be found under C++ methods and the 'this' object.

### ValueTypeBehavior

With this pragma you can change the way value types and sequences are handled.

Usually lower case names cannot be type names in JavaScript code. This is a problem because value type names are lower case. You can specify `Addressable` as value for this pragma to change this. If `Addressable` is specified a JavaScript value can be explicitly coerced to a specific, named, value type. This is done using the `as` operator, like you would do with object types. Furthermore, you can also check for value types using the `instanceof` operator:

     pragma ValueTypeBehavior: Addressable
     import QtQml

     QtObject {
      property var a
      property real b: (a as rect).x
      property bool c: a instanceof rect

      property var rect // inaccessible. "rect" is a type name.
     }

Since `rect` in the above example is now a type name, it will shadow any properties called `rect`.

Explicitly casting to the desired type helps tooling. It can allow the Qt Quick Compiler generate efficient code where it otherwise would not be able to. You can use qmllint to find such occurrences.

There is also a `Inaddressable` value you can use to explicitly specify the default behavior.

Another attribute to the `ValueTypeBehavior` pragma is `Assertable`, introduced in Qt 6.8. Due to a mistake in Qt 6.6 and 6.7 the `a as rect` above not only checks whether `a` is a `rect` but also constructs a `rect` if `a` is of a compatible type. This is obviously not what a type assertion should do. Specifying `Assertable` prevents this behavior and restricts type assertions for value types to only check for the type. You should always specify it if you are going to use value types with `as`. In any case, if the type assertion for a value type fails, the result is `undefined`.

`instanceof` does not have this problem since it only checks for inheritance, not for all possible type coercions.

Note: Using `as` with the `int` and `double` types is not advisable since by JavaScript rules, the result of any calculation is a floating point number, even if it happens to hold the same value as its integer equivalent. Conversely, any integer constant you declare in JavaScript is not a double by QML's type mapping rules. Furthermore, `int` and `double` are reserved words. You can only address these types via type namespaces.

Value types and sequences are generally treated as references. This means, if you retrieve a value type instance from a property into a local value, and then change the local value, the original property is also changed. Furthermore, if you write the original property explicitly, the local value is also updated. This behavior is rather unintuitive in many places, and you should not rely on it. The `Copy` and `Reference` values for the `ValueTypeBehavior` pragma are experimental options to change this behavior. You should not use them. Specifying `Copy` causes all value types to be treated as actual copies. Specifying `Reference` explicitly states the default behavior.

Rather than using `Copy` you should explicitly re-load references to value types and sequences any time they can have been affected by side effects. Side effects can happen whenever you call a function or imperatively set a property. qmllint provides guidance on this. For example, in the following code the variable `f` is affected by side effects after writing `width`. This is because there may be a binding in a derived type or in a `Binding` element that updates `font` when `width` is changed.

     import QtQuick
     Text {
      function a() : real {
          var f = font;
          width = f.pixelSize;
          return f.pointSize;
      }
     }

In order to address this, you can avoid holding `f` across the write operation on `width`:

     import QtQuick
     Text {
      function a() : real {
          var f = font;
          width = f.pixelSize;
          f = font;
          return f.pointSize;
      }
     }

This, in turn can be shortened to:

     import QtQuick
     Text {
      function a() : real {
          width = font.pixelSize;
          return font.pointSize;
      }
     }

You might assume that re-retrieving the `font` property is costly, but actually the QML engine automatically refreshes value type references each time you read from them. So this is not more expensive than the first version, but a clearer way to express the same operations.

### Translator

With this pragma you can set the context for the translations in the file.

     pragma Translator: myTranslationContext

     pragma Translator: "myTranslationContext"

For more information on internationalization with QML, see Use qsTr.

## Imports

A document must import the necessary modules or type namespaces to enable the engine to load the QML object types referenced within the document. By default, a document can access any QML object types that have been defined through `.qml` files in the same directory; if a document needs to refer to any other object types, it must import the type namespace into which those types have been registered.

QML does not have a preprocessor that modifies the document prior to presentation to the QML engine, unlike C or C++. The `import` statements do not copy and prepend the code in the document, but instead instruct the QML engine on how to resolve type references found in the document. Any type reference present in a QML document - such as `Rectangle` and `ListView` - including those made within a JavaScript block or property bindings, are resolved based exclusively on the import statements. At least one `import` statement must be present such as `import QtQuick 2.0`.

Please see the QML Syntax - Import Statements documentation for in-depth information about QML imports.

## The Root Object Declaration

A QML document describes a hierarchy of objects which can be instantiated. Each object definition has a certain structure; it has a type, it can have an id and an object name, it can have properties, it can have methods, it can have signals and it can have signal handlers.

A QML file must only contain a single root object definition. The following is invalid and will generate an error:

     // MyQmlFile.qml
     import QtQuick 2.0

     Rectangle { width: 200; height: 200; color: "red" }
     Rectangle { width: 200; height: 200; color: "blue" }    // invalid!

This is because a .qml file automatically defines a QML type, which encapsulates a single QML object definition. This is discussed further in Documents as QML object type definitions.

See also Type annotations and assertions.

QML Documents ◦ Defining Object Types in QML