JavaScript in QML

Like many features in Cascades, the implementation and use of JavaScript is based on the JavaScript implementation in Qt, but there are some differences. For more information about the Qt implementation, see Integrating JavaScript on the Qt website. Otherwise, continue reading the sections below to learn how to use JavaScript in Cascades.

For a complete list of JavaScript objects and functions that are supported in QML, see ECMAScript Reference in the Qt documentation.

JavaScript in signal handlers

The most common use of JavaScript in QML is within signal handlers. Inside signal handlers, you use JavaScript to determine what you want your app to do in response to the signal. You can set values for properties of QML components, perform calculations, or call other JavaScript functions that you define. Here's how to create a button that, when it's clicked, changes the size of a colored container. Using basic JavaScript code, the container alternates between two sizes when the button is clicked:

import bb.cascades 1.2
 
Page {
    Container {
        Button {
            text: "Change size"
             
            onClicked: {
                if (myContainer.preferredWidth == 200) {
                    myContainer.preferredWidth = 400;
                    myContainer.preferredHeight = 400;
                } else {
                    myContainer.preferredWidth = 200;
                    myContainer.preferredHeight = 200;
                }
            }
        }
         
        Container {
            id: myContainer
            preferredWidth: 200
            preferredHeight: 200
            background: Color.Blue
        }  
    }
}

Notice the difference in syntax between JavaScript and QML. You set the values of properties in JavaScript by using an equal sign (=) and you set the values in QML by using a colon (:).

For more information about signal handlers, see Signals and slots.

Creating custom JavaScript functions

You can write your own custom JavaScript functions in-line in QML. These functions become part of the QML component that contains them and you can call them by using the id property of the component. These functions can accept parameters and even return values that you can use elsewhere in your app.

Here's how to create a custom JavaScript function that calculates the Celsius equivalent of a Fahrenheit temperature value. You can type the Fahrenheit value in a text field, click a button, and the Celsius value appears as the text of a  Label below the text field:

import bb.cascades 1.2
 
Page {
    Container {
        id: root
 
        // The custom JavaScript function called convertTemp()
        function convertTemp(fahr) {
            fahr = parseInt(fahr);
            return ((fahr - 32) * 5) / 9;
        }
             
        Button {
            text: "Convert"
             
            onClicked: {
                tempOutput.text = 
                    "" + root.convertTemp(tempInput.text);
            }
        }
         
        TextField {
            id: tempInput
            preferredWidth: 150
            preferredHeight: 100
             
            // Display a keyboard that's appropriate for typing
            // temperatures
            inputMode: TextFieldInputMode.NumbersAndPunctuation
        }
         
        Label {
            id: tempOutput
            text: "0"
 
            // Use a text style to create text in a large font
            textStyle {
                base: SystemDefaults.TextStyles.BigText
            }
        } 
    }
}

Importing JavaScript code

If you have multiple JavaScript functions that you want to use, you can place them in a separate file and then import them into your app instead of defining them in QML. You can define these functions in a .js file that's located in the assets folder of your project, and use the import statement in your .qml file to import them and make them available in your app.

You must qualify the JavaScript files that you import by using the as keyword and providing a unique name for the file. This name can't be the same as any other modules that you import and can't be the same as any default JavaScript objects (such as Number or String).

For example, let's say that you create a file called tempFunctions.js that includes the convertTemp() function from the sample code in the previous section. Here's how to import that file and use the function in QML:

import bb.cascades 1.2
import "tempFunctions.js" as TemperatureFunctions
 
Page {
    Container {        
        Button {
            text: "Convert"
             
            onClicked: {
                // Call the convertTemp() function from the
                // imported JavaScript file
                tempOutput.text = "" +
                    TemperatureFunctions.convertTemp(tempInput.text);
            }
        }
         
        TextField {
            id: tempInput
            preferredWidth: 150
            preferredHeight: 100
             
            // Display a keyboard that's appropriate for typing
            // temperatures
            inputMode: TextFieldInputMode.NumbersAndPunctuation
        }
         
        Label {
            id: tempOutput
            text: "0"
             
            // Use a text style to create text in a large font
            textStyle {
                base: SystemDefaults.TextStyles.BigText
            }
        } 
    }
}

Connecting signals to JavaScript functions

In the previous sections, you learned how to call JavaScript functions from signal handlers (such as the onClicked signal handler for a  Button) in QML. Instead of calling a JavaScript function explicitly, you can connect the function to a signal. When the signal is emitted, the function is called automatically. The JavaScript function acts as a slot and allows you to connect signals to it.

Here's how to create a button that, when it's clicked, calls a custom JavaScript function that changes the text of a  Label. To connect the signal to the JavaScript function, you use a signal handler for the  Container control called onCreationCompleted. This signal handler is run in response to the creationCompleted() signal that's emitted after the container is created successfully and can be a good time to perform setup or initialization operations for your app:

import bb.cascades 1.2
 
Page {
    Container {
        id: root
         
        // The custom JavaScript function called changeText()
        function changeText() {
            if (myLabel.text == "First text string")
                myLabel.text = "Second text string";
            else
                myLabel.text = "First text string";
        }
                 
        Button {
            id: myButton
            text: "Change"
        }
         
        Label {
            id: myLabel
            text: "First text string"
            textStyle {
                base: SystemDefaults.TextStyles.BigText
            }
        }
         
        // When the container is created, connect the
        // button's clicked() signal to the custom JavaScript
        // function changeText()
        onCreationCompleted: {
            myButton.clicked.connect(root.changeText);
        }
    }
}

Last modified: 2014-05-14



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus