aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/doc/src/documents/scope.qdoc
blob: 9da77a4905baf39fb03fee0ea715d43d8cb76a12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file.  Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page qtqml-documents-scope.html
\title Scope and Naming Resolution
\brief overview of scope and naming resolution

QML property bindings, inline functions, and imported JavaScript files all
run in a JavaScript scope.  Scope controls which variables an expression can
access, and which variable takes precedence when two or more names conflict.

As JavaScript's built-in scope mechanism is very simple, QML enhances it to fit
more naturally with the QML language extensions.

\section1 JavaScript Scope

QML's scope extensions do not interfere with JavaScript's natural scoping.
JavaScript programmers can reuse their existing knowledge when programming
functions, property bindings or imported JavaScript files in QML.

In the following example, the \c {addConstant()} method will add 13 to the
parameter passed just as the programmer would expect irrespective of the
value of the QML object's \c a and \c b properties.

\code
QtObject {
    property int a: 3
    property int b: 9

    function addConstant(b) {
        var a = 13;
        return b + a;
    }
}
\endcode

That QML respects JavaScript's normal scoping rules even applies in bindings.
This totally evil, abomination of a binding will assign 12 to the QML object's
\c a property.

\code
QtObject {
    property int a

    a: { var a = 12; a; }
}
\endcode

Every JavaScript expression, function or file in QML has its own unique
variable object.  Local variables declared in one will never conflict
with local variables declared in another.

\section1 Type Names and Imported JavaScript Files

\l {QML Document}s include import statements that define the type names
and JavaScript files visible to the document.  In addition to their use in the
QML declaration itself, type names are used by JavaScript code when accessing
\l {Attached Properties} and enumeration values.

The effect of an import applies to every property binding, and JavaScript
function in the QML document, even those in nested inline components.  The
following example shows a simple QML file that accesses some enumeration
values and calls an imported JavaScript function.

\code
import QtQuick 2.0
import "code.js" as Code

ListView {
    snapMode: ListView.SnapToItem

    delegate: Component {
        Text {
            elide: Text.ElideMiddle
            text: "A really, really long string that will require eliding."
            color: Code.defaultColor()
        }
    }
}
\endcode

\section1 Binding Scope Object

Property bindings are the most common use of JavaScript in QML.  Property
bindings associate the result of a JavaScript expression with a property of an
object.  The object to which the bound property belongs is known as the binding's
scope object.  In this QML simple declaration the \l Item object is the
binding's scope object.

\code
Item {
    anchors.left: parent.left
}
\endcode

Bindings have access to the scope object's properties without qualification.
In the previous example, the binding accesses the \l Item's \c parent property
directly, without needing any form of object prefix.  QML introduces a more
structured, object-oriented approach to JavaScript, and consequently does not
require the use of the JavaScript \c this property.

Care must be used when accessing \l {Attached Properties} from bindings due
to their interaction with the scope object.  Conceptually attached properties
exist on \e all objects, even if they only have an effect on a subset of those.
Consequently unqualified attached property reads will always resolve to an
attached property on the scope object, which is not always what the programmer
intended.

For example, the \l PathView type attaches interpolated value properties to
its delegates depending on their position in the path.  As PathView only
meaningfully attaches these properties to the root object in the delegate, any
sub-object that accesses them must explicitly qualify the root object, as shown
below.

\code
PathView {
    delegate: Component {
        Rectangle {
            id: root
            Image {
                scale: root.PathView.scale
            }
        }
    }
}
\endcode

If the \l Image object omitted the \c root prefix, it would inadvertently access
the unset \c {PathView.scale} attached property on itself.

\section1 Component Scope

Each QML component in a QML document defines a logical scope.  Each document
has at least one root component, but can also have other inline sub-components.
The component scope is the union of the object ids within the component and the
component's root object's properties.

\code
Item {
    property string title

    Text {
        id: title
        text: "<b>" + title + "</b>"
        font.pixelSize: 22
        anchors.top: parent.top
    }

    Text {
        text: title.text
        font.pixelSize: 18
        anchors.bottom: parent.bottom
    }
}
\endcode

The example above shows a simple QML component that displays a rich text title
string at the top, and a smaller copy of the same text at the bottom.  The first
\c Text type directly accesses the component's \c title property when
forming the text to display.  That the root type's properties are directly
accessible makes it trivial to distribute data throughout the component.

The second \c Text type uses an id to access the first's text directly.  IDs
are specified explicitly by the QML programmer so they always take precedence
over other property names (except for those in the \l {JavaScript Scope}).  For
example, in the unlikely event that the binding's \l {Binding Scope Object}{scope
object}  had a \c titletype property in the previous example, the \c titletype
id would still take precedence.

\section1 Component Instance Hierarchy

In QML, component instances connect their component scopes together to form a
scope hierarchy.  Component instances can directly access the component scopes of
their ancestors.

The easiest way to demonstrate this is with inline sub-components whose component
scopes are implicitly scoped as children of the outer component.

\code
Item {
    property color defaultColor: "blue"

    ListView {
        delegate: Component {
            Rectangle {
                color: defaultColor
            }
        }
    }
}
\endcode

The component instance hierarchy allows instances of the delegate component
to access the \c defaultColor property of the \c Item type.  Of course,
had the delegate component had a property called \c defaultColor that would
have taken precedence.

The component instance scope hierarchy extends to out-of-line components, too.
In the following example, the \c TitlePage.qml component creates two
\c TitleText instances.  Even though the \c TitleText type is in a separate
file, it still has access to the \c title property when it is used from within
the \c TitlePage.  QML is a dynamically scoped language - depending on where it
is used, the \c title property may resolve differently.

\code
// TitlePage.qml
import QtQuick 2.0
Item {
    property string title

    TitleText {
        size: 22
        anchors.top: parent.top
    }

    TitleText {
        size: 18
        anchors.bottom: parent.bottom
    }
}

// TitleText.qml
import QtQuick 2.0
Text {
    property int size
    text: "<b>" + title + "</b>"
    font.pixelSize: size
}
\endcode

Dynamic scoping is very powerful, but it must be used cautiously to prevent
the behavior of QML code from becoming difficult to predict.  In general it
should only be used in cases where the two components are already tightly
coupled in another way.  When building reusable components, it is preferable
to use property interfaces, like this:

\code
// TitlePage.qml
import QtQuick 2.0
Item {
    id: root
    property string title

    TitleText {
        title: root.title
        size: 22
        anchors.top: parent.top
    }

    TitleText {
        title: root.title
        size: 18
        anchors.bottom: parent.bottom
    }
}

// TitleText.qml
import QtQuick 2.0
Text {
    property string title
    property int size

    text: "<b>" + title + "</b>"
    font.pixelSize: size
}
\endcode

\section1 Overridden Properties

QML permits property names defined in an object declaration to be overridden by properties
declared within another object declaration that extends the first.  For example:

\code
// Displayable.qml
import QtQuick 2.0
Item {
    property string title
    property string detail

    Text {
        text: "<b>" + title + "</b><br>" + detail
    }

    function getTitle() { return title }
    function setTitle(newTitle) { title = newTitle }
}

// Person.qml
import QtQuick 2.0
Displayable {
    property string title
    property string firstName
    property string lastName

    function fullName()  { return title + " " + firstName + " " + lastName }
}
\endcode

Here, the name \c title is given to both the heading of the output text for Displayable,
and also to the honorific title of the Person object.

An overridden property is resolved according to the scope in which it is referenced.
Inside the scope of the Person component, or from an external scope that refers
to an instance of the Person component, \c title resolves to the property
declared inside Person.qml.  The \c fullName function will refer to the \c title
property declared inside Person.

Inside the Displayable component, however, \c title refers to the property
declared in Displayable.qml.  The getTitle() and setTitle() functions, and the
binding for the \c text property of the Text object will all refer to the \c title
property declared in the Displayable component.

Despite sharing the same name, the two properties are entirely separate.  An
onChanged signal handler for one of the properties will not be triggered by
a change to the other property with the same name.  An alias to either property
will refer to one or the other, but not both.

\section1 JavaScript Global Object

QML disallows type, id and property names that conflict with the properties
on the global object to prevent any confusion.  Programmers can be confident
that \c Math.min(10, 9) will always work as expected!

See \l {JavaScript Host Environment} for more information.

*/