JavaScript in QML
The BlackBerry Native SDK and Cascades framework let you use several different programming languages to create apps for BlackBerry devices. You can:
- Use QML to design and implement UIs
- Use C++ for your application logic and device-specific functions
- Use C APIs and the BlackBerry Platform Services (BPS) library to access system features directly, such as screen, navigator, and accelerometer features
For more information about C APIs and BlackBerry Platform Services, see the BlackBerry 10 Native SDK documentation.
When you create your apps using QML, you can use JavaScript to supplement the functionality that QML provides. You can write signal handlers for QML components in JavaScript, create custom JavaScript functions that you can call from anywhere in your app, and import custom JavaScript code from an external file. You can even connect signals of QML components directly to JavaScript functions.
Like many features in Cascades, the implementation and use of JavaScript is based on the JavaScript implementation in Qt. There are some differences, so the following sections describe how to use JavaScript in Cascades. For more information about using JavaScript in QML, see qt-project.org/doc/qt-4.8/qdeclarativejavascript.html.
Using JavaScript in signal handlers
If you've worked through any other documentation or tutorials on this site, you may have seen this use of JavaScript already. Most core UI control in Cascades include predefined signals that are emitted when something happens to the control. For example, the Button control emits the clicked() signal (which is inherited from AbstractButton) when it's clicked. Cascades provides signal handlers for these predefined signals automatically, and you can use these handlers to respond to the signal when it's emitted. For more information about signals, see Signals and slots.
Inside signal handlers, you use JavaScript to determine what you want your app to do in response to a 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.0
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 (:).
Creating custom JavaScript functions
You can write your own custom JavaScript functions inline 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.0
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 from a separate file
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 also can't be the same as any predefined 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.0
import "tempFunctions.js" as TemperatureFunctions
Page {
content: 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. For more information about connecting signals and slots in Cascades, see Signals and slots.
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, we use a signal handler for the Container control called onCreationCompleted. This signal handler is executed 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.0
Page {
content: 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);
}
}
}
What's next?
Now that you've learned the basics of JavaScript in Cascades, check out the sample apps (most of them use JavaScript in QML) or follow a tutorial that teaches you how to create other custom JavaScript functions.
Last modified: 2013-03-21