Widget Basics
The UI of a Tabris.js app consists of native widgets, represented by JavaScript objects. There are different types of widgets such as Button
, TextView
, or ScrollView
. Every widget type is a subtype of Widget which provides common methods to get and set properties, be notified of events, and append widgets to a parent widget. Most of these methods return the widget itself to allow method chaining.
Creating Native Widgets
Every widget constructor accepts an object with initial property values to create the native widget with. Here’s how you create and initialize a widget in Tabris.js:
let button = new Button({
left: 10,
top: 10,
text: 'OK'
});
If you prefer declarative UI, you may also use JSX
to create widgets. When you generate a Tabris.js TypeScript project, JSX support is already set up.
Widget Properties
Every native widget supports a set of properties (e.g. a text or a color). These properties can be read and written directly or using the Widget’s get()
and set()
methods.
widget.text = 'Hello World';
let text = widget.text;
Example with get()
and set()
:
widget.set('text', 'Hello World');
let text = widget.get('text');
Like with the constructor, it’s also possible to set multiple property values:
button.set({
text: 'OK',
background: 'blue'
});
When trying to set an invalid value (e.g. a value of the wrong type), the value will be converted if possible, otherwise it will be ignored with a warning printed to the developer console. The set()
method will also print a warning for unsupported properties.
Events
Widgets can notify listeners of events such as a user interaction or a property change. Event listeners can be added using the methods on()
and once()
, and removed using off()
.
Example:
function selectionHandler(event) {
console.log('Button ' + event.target.text + ' selected!');
}
button.on('select', selectionHandler);
The listener function is called with an instance of EventObject that may include a number of additional properties depending on the event type.
Event types are case sensitive.
A context object may be given as the third parameter to on()
. This object will then be available as this
inside the listener function.
function selectionHandler() {
console.log(this.foo);
}
button.on('select', selectionHandler, {foo: 'Hello World'});
The method once()
does the same as on()
, but it removes the listener after it has been invoked by an event.
To remove a listener, use the method off()
.
Change Events
All widgets support property change events that are fired when a property value changes. All change events are named [propertyName]Changed
and provide a ChangeEvent
.
In addition to the common event properties, change events have a property value
that contains the new value of the property.
Example:
new TextInput().on('textChanged', (event) => {
console.log('The text has changed to: ' + event.value);
})
It’s often convenient to use the ES6 destructuring syntax for the event parameter, which allows to extract event properties as named variables:
checkBox.on('selectionChanged', ({target, value: checked}) => {
target.text = checked ? 'checked' : 'unchecked';
})
Animations
All widgets have the method animate(properties, options)
. It expects a map of properties to animate (akin to the set
method), and a set of options for the animation itself.
All animated properties are set to their target value as soon as the animation starts. Therefore, calling get
will always return either the start or target value, never one in between.
Only the properties transform
and opacity
can be animated.
The animate
method returns a Promise that is resolved once the animation is completed. If the animation is aborted, e.g. by disposing the widget, the promise is rejected.
Example:
label.animate({
opacity: 0,
transform: {
translationX: 200,
scaleX: 0.1
}
}, {
duration: 1000,
easing: 'ease-out'
}).then(() => label.dispose());
The Widget Tree
Setting the Parent
To become visible, a widget needs a parent. The top-level parent of all widgets is the content view (ui.contentView
). Widgets can be included in the widget hierarchy using append()
or appendTo()
.
Example:
let button = new Button({
text: 'OK',
...
}).appendTo(parent);
If the widget already has a parent, it is removed from the actual parent and appended to the new one. An addChild event is triggered on the parent.
It’s also possible to add multiple widgets to the same parent using append()
:
page.append(okButton, cancelButton);
Traversing
See also: Selector API
The current parent of a widget is returned by the parent
method,
and the children by the children
method.
Example:
let parent = widget.parent();
let firstChild = parent.children()[0];
let lastChild = parent.children().last();
The result list of children is an array-like object of the type WidgetCollection
.
Disposing of a Widget
The dispose
method disposes of the widget and all of its children. It triggers a removeChild event on the parent and a dispose event on itself.
Example:
button.on('dispose', () => console.log('Button disposed!'));
button.dispose();
After a widget is disposed none of its methods will work except isDisposed()
, which returns true
if the widget has been disposed, otherwise false
.