Cross Reference: /yui3/src/attribute/docs/index.mustache
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
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<div class="intro">
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>The Attribute utility allows you to add attributes to any class through an augmentable Attribute interface.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai The interface adds `get and `set methods to your class to retrieve and store attribute values, as well as
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai support for change events that can be used to listen for changes in attribute values.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>In addition, attributes can be configured with custom getters, setters and validators, allowing the developer to
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai normalize and validate values being stored or retrieved. Attributes can also be specified as read-only or write-once.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai</div>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai{{>getting-started}}
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h2 id="augment">Augmenting Your Class With Attribute</h2>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>The Attribute class is designed to be augmented to an existing class (we'll refer to this class as the 'host' class) and adds attribute
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaimanagement support to it. For example, assuming you have a class constructor, `MyClass, to which you'd like to add attribute support,
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiyou can simply augment your class with Attribute, as shown below:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen DesaiYUI().use("attribute", function(Y) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai function MyClass() {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai ...
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai }
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai Y.augment(MyClass, Y.Attribute);
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai});
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Instances of your class will now have Attribute methods available, which your class can use to configure attributes for itself, and which users of your
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiclass can use to get and set attribute values. See the <a href="{{apiDocs}}/Attribute.html">Attribute API documentation</a> for a complete list of
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaimethods which Attribute will add to your class.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Note that in general, rather than augmenting Attribute directly, most implementations will simply extend <a href="../base/index.html">Base</a>, which
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiaugments Attribute, and handles attribute setup for you. Base also sets up all attributes to be lazily initialized (initialized on the first call to get or set) by default, improving performance.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h2 id="adding">Adding Attributes</h2>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Once augmented with Attribute, your class can either use the `addAttrs` method to setup attributes en mass, or use the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai`addAttr` method, to add them individually. `addAttrs` is tailored towards use by host classes, since in addition
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaito being able to initialize multiple attributes in one call, it also accepts an additional name/value hash, which can be used to allow the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiuser to define the initial value of attributes when instantiating Attribute driven classes, as shown below:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai...
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaifunction MyClass(userValues) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // Use addAttrs, to setup default attributes for
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // your class, and mixing in user provided initial values.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai var attributeConfig = {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai attrA : {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // ... Configuration for attribute "attrA" ...
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai },
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai attrB : {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // ... Configuration for attribute "attrB" ...
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai }
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai };
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai this.addAttrs(attributeConfig, userValues);
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai};
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Users of your class now have the ability to pass attribute values to the constructor,
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaior set values using the `set` method as shown below:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai// Set initial value for attrA during instantiation
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaivar o = new MyClass({
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai attrA:5
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai});
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai// Set attrB later on
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.set("attrB", "Hello World!");
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h2 id="configuration">Attribute Configuration Properties</h2>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Each attribute you add can be configured with the properties listed in the table below (all properties are optional and case-sensitive):</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<table>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <caption>Attribute Configuration Properties</caption>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <thead>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <th>Property Name</th>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <th>Type</th>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <th>Description</th>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
e6180acff02ff08d123f76824eb765a7c25c5bf2Satyen Desai </thead>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tbody>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`value`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>Any</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>The default value for this attribute</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`valueFn`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>Function</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>A function, the return value of which is the value for the attribute. This property can be used instead of the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai value property for static configurations, if you need to set default values which require access to instance state
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai ("this.something").</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>If both the value and valueFn properties are defined, the value returned by valueFn has precedence over the value property,
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai unless it returns undefined, in which case the value property is used.</p>
cbbb7a9af1f572d0562409e9e2dabe206de93524Satyen Desai
cbbb7a9af1f572d0562409e9e2dabe206de93524Satyen Desai <p>The valueFn is passed the name of the attribute, allowing users to share valueFn implementations across attributes if required.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`getter`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>Function</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>Custom 'get' handler, which is invoked when the user calls Attribute's `get` method. It can
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai be used to manipulate or normalize the stored value before it is returned to the user.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>The function will be passed the currently stored value of the attribute as the first argument and the name
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai of the attribute as the second argument. If configured, the value returned by this function will be
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai the value returned to the user.</p>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai <p>Attribute also supports the ability to return sub-attribute values (`get('a.b.c')`). The getter implications for
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai this are discussed in the <a href="#subattrs-gsv">Getters, Setters, Validators and Sub Attributes</a> section.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`setter`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>Function</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>Custom 'set' handler, which is invoked when the user calls Attribute's `set` method. It can
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai be used to manipulate the value which is stored for the attribute.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>The function will be passed the value which the user passed to the set method as the first
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai argument and the name of the attribute as the second argument. If configured, the value returned by this
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai function will be the value stored as the attribute value.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>The getter and setter can be used to normalize values on input/output for the user while storing the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai value in a format most effective for internal operation.</p>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai <p>Attribute also supports the ability to set sub-attribute values (`set('a.b.c', 10)`). The setter
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai implications for this are discussed in the <a href="#subattrs-gsv">Getters, Setters, Validators and Sub Attributes</a>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai section.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`validator`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>Function</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>Validation function, which if defined, is called before the `setter`.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai The validation function is passed the value which the user is trying to set as the first argument and the name of the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai attribute as the second argument.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>If the function returns `false`, the attribute's stored value is not updated (and the `setter`, if defined, will not be invoked).
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai If it returns `true`, the `setter` is invoked if defined, and the attribute's stored value is updated.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>If validation is a potentially expensive task and contains code which would be repeated in a `setter` (for example, converting a string to a Node reference),
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai you can combine validation into the `setter` function, by returning `Attribute.INVALID_VALUE` from a `setter` if it
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai encounters an invalid value.</p>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai <p>Attribute also supports the ability to set sub-attribute values (set('a.b.c', 10)). The 'validator'
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai implications for this are discussed in the <a href="#subattrs-gsv">Getters, Setters, Validators and Sub Attributes</a>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai section.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`readOnly`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>boolean</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai Configures the attribute to be read-only. Users will not be able to set the value of the attribute using
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai Attribute's public API.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`writeOnce`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>boolean or "initOnly"</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>Configures the attribute to be write-once. Users will only be able to set the value of the attribute using
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai Attribute's `set` method once. Once a value has been set for the attribute, calling `set` will not change it's value.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>If set to "initOnly", the attribute can only be set during initialization. In the case of Base, this means that the attribute can
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai only be set through the constructor.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>Code within your class can update the value of readOnly or writeOnce attributes by using the private `_set` method.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`broadcast`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>int</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai By default attribute change events are not broadcast to the YUI instance or global YUI object. The broadcast property
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai can be used to set specific attribute change events to be broadcast to either the YUI instance or the global YUI object.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai See CustomEvent's <a href="{{apiDocs}}/CustomEvent.html#property_broadcast">broadcast</a> property for valid values.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`lazyAdd`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>boolean</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai Whether or not to delay initialization of the attribute until the first call to get/set it.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai This flag can be used to over-ride lazy initialization on a per attribute basis, when adding multiple attributes through
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai the <a href="{{apiDocs}}/Attribute.html#method_addAttrs">`addAttrs`</a> method.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </p>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai <p>When extending Base, all attributes are added lazily, so this flag can be used to over-ride
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai lazyAdd behavior for specific attributes.</p>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai <p><strong>The only reason you should need to disable `lazyAdd` is if your setter is doing more
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai than normalizing the attribute value</strong>. For example if your setter is storing some other state, in `this._someProp`, which is being used
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai by other parts of your component. In this case, since you're not getting or setting the attribute to access `this._someProp`,
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai it won't get set up lazily, until someone actually calls `get` or `set` for the related attribute.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>`cloneDefaultValue`</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>"shallow", "deep", true, false</td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai This configuration value is not actually supported by Attribute natively, but is available when
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai working with Base, and defining attribute configurations using Base's static `<a href="{{apiDocs}}/Base.html#property_Base.ATTRS">ATTRS</a>` property.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai This property controls how the statically defined default `value` field in Base's `ATTRS` attribute configuration is handled,
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai when setting it up as the value for an instance. By default (if this property is not defined) object literals and arrays are deep cloned, to protect the default value from
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai being modified. Setting cloneDefaultValue to `false` will disable cloning. This is useful in cases where you intend to use arrays or
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai object literals by reference (e.g. they point to utilities). A shallow clone will be used if cloneDefaultValue is set to `"shallow"` and a
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai deep clone will be used for `"deep"` or `true`.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </td>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tr>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai </tbody>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai</table>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h4 id="howtoconfig">Configuring Attributes</h4>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>The above attribute properties are set using an object with property name/value pairs, which is passed to either `addAttrs` or `addAttr` as the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiconfiguration argument. For example, expanding on the code snippet above:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai...
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaivar attributeConfig = {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai attrA : {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // Configuration for attribute "attrA"
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai value: 5,
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai setter: function(val) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai return Math.min(val, 10);
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai },
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai validator: function(val) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai return Y.Lang.isNumber(val);
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai }
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai },
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai attrB : {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // Configuration for attribute "attrB"
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai }
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai};
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaithis.addAttrs(attributeConfig, userValues);
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai...
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Or, if using `addAttr`:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaithis.addAttr("attrA", {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // Configuration for attribute "attrA"
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai value: 5,
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai setter: function(val) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai return Math.min(val, 10);
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai },
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai validator: function(val) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai return Y.Lang.isNumber(val);
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai }
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai});
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h2 id="events">Attribute Change Events</h2>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>The availability of attribute change events are one of the key benefits of using
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiattributes to store state for your objects, instead of regular object properties.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen DesaiAttribute change events are fired whenever `set` is invoked for an
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiattribute, allowing you to execute code in response to a change in the attribute's
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaivalue.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h4>Listening for Change Events</h4>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Attribute change events are Custom Events, having the type: "[attributeName]Change", where
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai[attributeName] is the name of the attribute which you're monitoring for changes.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>For example, if you were interested in listening for changes to an attribute named
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai"enabled", you would subscribe to events of type "enabledChange".</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.on("enabledChange", function(event) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // Do something just before "enabled" is about to be set
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai});
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p><em>NOTE:</em> Context and additional arguments for the listener function can either be
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaidefined using YUI's `bind` method, or by passing in the context and
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiadditional arguments to the `on` method.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Attribute change event listeners can be registered using either the `on`
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai(as shown above) or `after` Attribute methods.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h4>On vs. After</h4>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h5>On</h5>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Listeners registered using the `on` method, are notified <strong>before</strong> the stored state of the attribute has been updated.
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen DesaiFunctions registered as "on" listeners receive an `Event` object as the first argument (actually an
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiinstance of <a href="{{apiDocs}}/EventFacade.html">`EventFacade`</a>) which contains information
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiabout the attribute being modified.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Since these listeners are invoked before any state change has occurred, they have the ability to
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiprevent the change in state from occurring, by invoking `event.preventDefault()` on
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaithe event object passed to them, or to modify the value being set, by modifying the `event.newVal` property.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.on("enabledChange", function(event) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // event.prevVal will contain the current attribute value
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai var val = event.prevVal;
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai if (val !== someCondition) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // Prevent "enabled" from being changed
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai event.preventDefault();
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai }
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai});
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h5>After</h5>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Listeners registered using the `after` method, are notified <strong>after</strong>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaithe stored state of the attribute has been updated. As with "on" listeners, the subscribed function
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaireceives an `Event` object as the first parameter.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Based on the definition above, "after" listeners are not invoked if state change is prevented,
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaifor example, due to one of the "on" listeners calling `preventDefault` on the event object.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.after("enabledChange", function(event) {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // event.newVal will contain the currently set value
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai var val = event.newVal;
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai // Calling preventDefault() in an "after" listener has no impact
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai event.preventDefault();
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai});
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h4>The Event Object</h4>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>The event facade passed to attribute change event listeners, has a number of attributes which provide information about the attribute being modified,
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaias well methods used to manage event propagation. These are described below:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<dl>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dt>newVal</dt>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dd>The value which the attribute will be set to (in the case of "on" listeners), or has been set to (in the case of "after" listeners)</dd>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dt>prevVal</dt>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dd>The value which the attribute is currently set to (in the case of "on" listeners), or was previously set to (in the case of "after" listeners)</dd>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dt>attrName</dt>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dd>The name of the attribute which is being set</dd>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dt>subAttrName</dt>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dd><p>Attribute also allows you to set individual properties of attributes having values which are objects through the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai `set` method (e.g. `o.set("X.a.b", 5)`, discussed below). This event property will contain the complete dot notation path for the object property which was changed.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <p>For example, during `o.set("X.a.b", 5);`, `event.subAttrName` will be `"X.a.b"`, the path of the property which was modified, and `event.attrName` will be `"X"`, the attribute name.</p></dd>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dt>preventDefault()<dt>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dd>This method can be called in an "on" listener function to prevent the attribute's value from being updated (the default behavior). Calling this method in an "after" listener has no impact, since the default behavior has already been invoked.</dd>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dt>stopImmediatePropagation()</dt>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai <dd>This method can be called in "on" or "after" listener functions, and will prevent the rest of the listener stack from
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai being notified, but will not prevent the attribute's value from being updated (viz. will not prevent the default behavior).</dd>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai</dl>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h2 id="attrsetflow">Attribute Set Flow Diagram</h2>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>The diagram below shows the order in which attribute setters, validators and change event subscribers are invoked during the set operation:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
d609add4939a337f393789c30b93add391550369Satyen Desai<p><a href="setflow.html" title="Click too see full-size image"><img src="{{componentAssets}}/img/attribute-set-flow.png" alt="Flow diagram for the attribute 'set' operation" height="466" width="538"></a></p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p><em>NOTE:</em> Any decision blocks for which an exit path is not explicitly shown will effectively exit the set operation, without storing the new value. These paths are not explicitly shown, in order to avoid clutter.</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<h2 id="subattrs">Getting/Setting Sub Attribute Values</h2>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>If you have attribute values which are objects (as opposed to primitive values, such as numbers or booleans), the `set` method will let
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiyou set properties of the object directly, using a dot notation syntax. For example, if you have an attribute, "strings" with the following value:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.set("strings", {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai ui : {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai accept_label : "OK",
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai decline_label : "Cancel",
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai },
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai errors : {
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai e1000 : "Not Supported",
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai e1001 : "Network Error"
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai }
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai});
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>You can set individual properties on the "strings" attribute value object, without having to get and then set the whole string's attribute value. This is done
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiby using the dot notation to reference properties within the attribute's value:</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai// Set existing properties
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.set("strings.ui.accept_label", "Yes");
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.set("strings.ui.decline_label", "No");
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai// Add a new property
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.set("strings.errors.e2000", "New Error");
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai// Cannot set new intermediate properties:
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai// "strings.messages" does not exist so can't set
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai// "strings.messages.intro"
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaio.set("strings.messages.intro", "Welcome");
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>Setting sub attribute values, will fire an attribute change event for the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaimain attribute (`"stringsChange"` in the above example), however the event object passed
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaito the listeners with have a "subAttrName" property set to reflect the full path to the
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaiattribute set (e.g. `event.subAttrName` will be `"strings.ui.accept_label"` for the set call on line 2 in the code snippet above).</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai<p>You can also retrieve sub attribute values using the same dot notation syntax</p>
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai// Get the string for the accept label
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desaivar lbl = o.get("strings.ui.accept_label");
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai```
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai<h3 id="subattrs-gsv">Getters, Setters, Validators and Sub Attributes</h3>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai<p>Getter, setter and validator attribute configuration functions are only defined for the top level
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desaiattribute (`"strings"` in this case) and will be invoked when getting/setting sub attribute values.
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen DesaiWhat this means is that getters and setters should always return the massaged value for the top level
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desaiattribute (e.g. `"strings"`), and not the sub attribute value being set (e.g. `"strings.ui.accept_label"`).
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen DesaiThe sub attribute being set is passed in as the second argument to the getter/setter/validator, so that it
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desaican fork for sub attribute handling if required.</p>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai<p>For example:</p>
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai```
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desaithis.addAttr("strings", {
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai getter : function(val, fullName) {
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai // 'fullName' is "strings.errors.e4500"
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai // 'val' is the whole strings hash: { ui : {...}, errors : {...}}.
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai // 'path' is ["strings", "errors", "e4500"]
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai var path = fullName.split(".");
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai if (path.length > 1) {
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai // Someone's asking for a sub-attribute value
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai // Maybe we want to do some special normalization just for this use case.
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai // For example, return a default error message instead of undefined.
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai path.shift();
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai if (path[0] == "errors") {
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai var leafValue = Y.Object.getValue(val, path);
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai if (leafValue === undefined) {
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai Y.Object.setValue(val, path, "Unknown Error");
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai }
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai }
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai }
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai // In either case (sub attribute or not) val is always the full hash for the 'strings' attribute.
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai return val;
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai }
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai});
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai```
4dd435e41f240005cb105adb10530f36a3a7c11bSatyen Desai
2956ea0ec4de894b7f8d43f9f79b3cbbbc022ac7Satyen Desai