Custom QML components

Even though Cascades comes with lots of useful controls right out of the box, you'll likely come to a point where you must create your own custom components.

Custom components are reusable UI components that can be used just like any other component that comes with the framework.

A common way of creating custom components is by compositing existing Cascades controls. For example, in a messaging application, you might want to create a ContactView control that displays a user's name and profile picture, and a DetailsView control that lists a user's contact information.

Another way of creating custom controls is by subclassing the  CustomControl class in C++. To read more about subclassing CustomControl, see Using C++ classes in QML.

Custom components in QML

A custom component is essentially a QML document that defines a single QML component that you can use in an application. During runtime, QML components are interpreted to create objects according to the behaviors defined by the document.

To create a QML component, you create a file called <Name>.qml, where <Name> is the new component name, that begins with an uppercase letter.

Here's an example of a simple custom component that combines a CheckBox and a Label. The component is defined in a file called CustomCheckBox.qml.

Cascades customQML checkbox 143px
import bb.cascades 1.0
 
Container {
    layout: StackLayout {
        orientation: LayoutOrientation.LeftToRight
    }
    CheckBox {
        id: checkBox
        checked: false
    }
    Label {
        id: label
        leftMargin: 10
        text: "Check Box"
    }
}

Using a custom component

To use a custom component in an application, you use the component name the way you would with any core component.

Below is an example of how you could use the CustomCheckBox component in another QML document. The component is assigned an id and has layout properties set on it. The CustomCheckBox.qml file must be located in the same directory as this file.

import bb.cascades 1.0
 
Page {
    Container {
        layout: DockLayout {}
        CustomCheckBox {
            id: customCheckBox
            verticalAlignment: VerticalAlignment.Center
            horizontalAlignment: HorizontalAlignment.Center
        }
    }
}

Accessing a component's properties

When you create a custom component, you'll often want to be able to expose the properties of its subcomponents. In the example above, CustomCheckBox contains a  CheckBox and a  Label, and each control has its own set of properties. However, in the custom component's current state, these inner properties cannot be accessed from outside the component. And what good is this CustomCheckBox if you can't change its text?

To expose these properties, you must define new properties at the root of your custom component and bind them to the inner properties that you want to expose.

In the example below, the text property for the Label and the checked property for the CheckBox are exposed for CustomCheckBox.

import bb.cascades 1.0
 
Container {
    property string text: label.text
    property bool checked: checkBox.checked   
     
    CheckBox {
        id: checkBox
        checked: false
    }
    Label {
        id: label
        text: "Hello"
    }
}

When you define a new property to expose an inner property, new memory is allocated for the property value. To avoid the allocation of new memory, you can use an alias to point to the inner property instead. Since the new property is of the same type as the aliased property, it's not necessary to specify an explicit type for the new property.

import bb.cascades 1.0
 
Container {
    property alias text: label.text
    property alias checked: checkBox.checked
     
    CheckBox {
        id: checkBox
        checked: false
    }
    Label {
        id: label
        text: "Hello"
    }
}

When you declare a custom property in QML, there's a corresponding value-change signal that's emitted when the property changes. To receive these signals, create a signal handler named using on<PropertyName>Changed syntax. In the example described above, the corresponding signal handlers are called onTextChanged and onCheckedChanged.

Here's how you can capture changes to the properties and log the new values.

import bb.cascades 1.0
 
Container {
    property alias text: label.text
    property alias checked: checkBox.checked
    
    ...

    onTextChanged: {
        console.log("Text has changed to:", text)
    }
    onCheckedChanged: {
        console.log("Checked has changed to:", checked)
    }
}

Last modified: 2013-03-21