@maccesar/titools 2.2.12 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +255 -713
- package/bin/titools.js +9 -1
- package/lib/cache.js +49 -0
- package/lib/commands/auto-update.js +138 -0
- package/lib/commands/skills.js +11 -0
- package/lib/commands/uninstall.js +17 -1
- package/lib/commands/update.js +5 -6
- package/lib/config.js +3 -0
- package/lib/downloader.js +10 -0
- package/lib/hooks.js +59 -0
- package/lib/utils.js +1 -0
- package/package.json +1 -1
- package/skills/alloy-guides/SKILL.md +46 -48
- package/skills/alloy-guides/references/CONTROLLERS.md +4 -6
- package/skills/alloy-guides/references/MODELS.md +340 -184
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +3 -4
- package/skills/alloy-guides/references/VIEWS_STYLES.md +44 -46
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +4 -5
- package/skills/alloy-guides/references/VIEWS_XML.md +51 -17
- package/skills/alloy-guides/references/WIDGETS.md +1 -1
- package/skills/alloy-howtos/SKILL.md +12 -13
- package/skills/alloy-howtos/references/cli_reference.md +40 -41
- package/skills/alloy-howtos/references/samples.md +3 -4
- package/skills/purgetss/SKILL.md +369 -356
- package/skills/purgetss/references/EXAMPLES.md +24 -25
- package/skills/purgetss/references/animation-advanced.md +555 -0
- package/skills/purgetss/references/animation-system.md +395 -995
- package/skills/purgetss/references/apply-directive.md +111 -141
- package/skills/purgetss/references/arbitrary-values.md +206 -480
- package/skills/purgetss/references/class-categories.md +277 -0
- package/skills/purgetss/references/class-index.md +1 -420
- package/skills/purgetss/references/cli-commands.md +446 -556
- package/skills/purgetss/references/configurable-properties.md +163 -599
- package/skills/purgetss/references/custom-rules.md +33 -76
- package/skills/purgetss/references/customization-deep-dive.md +319 -518
- package/skills/purgetss/references/dynamic-component-creation.md +33 -37
- package/skills/purgetss/references/grid-layout.md +42 -371
- package/skills/purgetss/references/icon-fonts.md +82 -475
- package/skills/purgetss/references/installation-setup.md +159 -331
- package/skills/purgetss/references/migration-guide.md +54 -109
- package/skills/purgetss/references/opacity-modifier.md +25 -222
- package/skills/purgetss/references/performance-tips.md +2 -2
- package/skills/purgetss/references/platform-modifiers.md +21 -407
- package/skills/purgetss/references/tikit-components.md +237 -104
- package/skills/purgetss/references/titanium-resets.md +20 -21
- package/skills/purgetss/references/ui-ux-design.md +171 -1702
- package/skills/ti-api/SKILL.md +109 -0
- package/skills/ti-api/references/api-android.md +675 -0
- package/skills/ti-api/references/api-app-platform.md +636 -0
- package/skills/ti-api/references/api-core.md +764 -0
- package/skills/ti-api/references/api-data-network.md +641 -0
- package/skills/ti-api/references/api-media.md +655 -0
- package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
- package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
- package/skills/ti-api/references/api-modules-map.md +632 -0
- package/skills/ti-api/references/api-modules-nfc.md +725 -0
- package/skills/ti-api/references/api-modules-social-misc.md +526 -0
- package/skills/ti-api/references/api-services.md +700 -0
- package/skills/ti-api/references/api-ui-android.md +499 -0
- package/skills/ti-api/references/api-ui-extras.md +702 -0
- package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
- package/skills/ti-api/references/api-ui-ios.md +756 -0
- package/skills/ti-api/references/api-ui-lists.md +581 -0
- package/skills/ti-api/references/api-ui-text-input.md +607 -0
- package/skills/ti-api/references/api-ui-views.md +572 -0
- package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
- package/skills/ti-api/references/api-xml-global.md +743 -0
- package/skills/ti-expert/SKILL.md +46 -45
- package/skills/ti-expert/references/adaptive-layouts.md +414 -0
- package/skills/ti-expert/references/alloy-builtins.md +16 -20
- package/skills/ti-expert/references/alloy-structure.md +40 -42
- package/skills/ti-expert/references/anti-patterns.md +34 -0
- package/skills/ti-expert/references/code-conventions.md +5 -3
- package/skills/ti-expert/references/error-handling.md +14 -7
- package/skills/ti-expert/references/examples.md +4 -2
- package/skills/ti-expert/references/performance-optimization.md +26 -24
- package/skills/ti-expert/references/security-device.md +17 -14
- package/skills/ti-expert/references/security-fundamentals.md +60 -101
- package/skills/ti-expert/references/state-management.md +15 -14
- package/skills/ti-expert/references/testing-e2e-ci.md +30 -21
- package/skills/ti-expert/references/theming.md +12 -20
- package/skills/ti-guides/SKILL.md +13 -17
- package/skills/ti-guides/references/advanced-data-and-images.md +30 -10
- package/skills/ti-guides/references/application-frameworks.md +3 -3
- package/skills/ti-guides/references/coding-best-practices.md +31 -2
- package/skills/ti-guides/references/commonjs-advanced.md +46 -4
- package/skills/ti-guides/references/hello-world.md +9 -13
- package/skills/ti-guides/references/hyperloop-native-access.md +4 -1
- package/skills/ti-guides/references/javascript-primer.md +13 -5
- package/skills/ti-guides/references/resources.md +0 -2
- package/skills/ti-guides/references/style-and-conventions.md +1 -0
- package/skills/ti-guides/references/tiapp-config.md +0 -32
- package/skills/ti-howtos/SKILL.md +43 -45
- package/skills/ti-howtos/references/buffer-codec-streams.md +25 -3
- package/skills/ti-howtos/references/debugging-profiling.md +14 -25
- package/skills/ti-howtos/references/google-maps-v2.md +3 -3
- package/skills/ti-howtos/references/ios-map-kit.md +8 -1
- package/skills/ti-howtos/references/notification-services.md +0 -1
- package/skills/ti-howtos/references/webpack-build-pipeline.md +3 -0
- package/skills/ti-ui/SKILL.md +47 -49
- package/skills/ti-ui/references/application-structures.md +3 -2
- package/skills/ti-ui/references/orientation.md +17 -9
- package/skills/ti-ui/references/platform-ui-ios.md +63 -0
- package/skills/ti-ui/references/scrolling-views.md +39 -0
|
@@ -259,9 +259,253 @@ If you want to fire or listen to multiple events, Backbone.js uses spaces to del
|
|
|
259
259
|
|
|
260
260
|
## Alloy Data Binding
|
|
261
261
|
|
|
262
|
+
### Introduction
|
|
263
|
+
|
|
264
|
+
When data in the collection changes, you may want to update the view simultaneously to keep information synchronized. This concept is known as data binding. Both Alloy and Backbone provide some mechanisms to bind model data to a view.
|
|
265
|
+
|
|
266
|
+
### Alloy Binding
|
|
267
|
+
|
|
268
|
+
In Alloy, collection data can be synchronized to a view object, or a single model can be bound to a view component. Alloy monitors the Backbone add, change, destroy, fetch, remove, and reset events to update the data in the view.
|
|
269
|
+
|
|
270
|
+
#### Collection-View Binding
|
|
271
|
+
|
|
272
|
+
To enable collection-view binding, create a global singleton or controller-specific collection using the [Collection tag](https://titaniumsdk.com/guide/Alloy_Framework/Alloy_Guide/Alloy_Views/Alloy_XML_Markup.html#collection-element) in the XML markup of the main view, then add the view object you want to bind data to. The following Titanium view objects support binding to a Collection:
|
|
273
|
+
|
|
274
|
+
| View Object | Since Alloy version | Add data binding attributes to... | Repeater Object to map model attributes to view properties |
|
|
275
|
+
| -------------- | ------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
276
|
+
| ButtonBar | 1.1 | `<Labels>` | `<Label/>` |
|
|
277
|
+
| CoverFlowView | 1.1 | `<Images>` | `<Image/>` |
|
|
278
|
+
| ListView | 1.2 | `<ListSection>` | `<ListItem/>` |
|
|
279
|
+
| Map Module | 1.4 | `<Module module="ti.map" method="createView">` | None, model attributes will be used as params for createAnnotation() directly. |
|
|
280
|
+
| Picker | 1.5 | `<PickerColumn>` or `<Column>` | `<PickerRow/>` or `<Row/>` |
|
|
281
|
+
| ScrollableView | 1.1 | `<ScrollableView>` | `<View/>` May contain children view objects. |
|
|
282
|
+
| TableView | 1.0 | `<TableView>` | `<TableViewRow/>` May contain children view objects. |
|
|
283
|
+
| TabbedBar | 1.1 | `<Labels>` | `<Label/>` |
|
|
284
|
+
| Toolbar | 1.1 | `<Items>` | `<Item/>` |
|
|
285
|
+
| View | 1.0 | `<View>` | Any view object except a top-level container like a Window or TabGroup |
|
|
286
|
+
|
|
287
|
+
You need to specify additional attributes in the markup, which are only specific to collection data binding. The only mandatory attribute is `dataCollection`, which specifies the collection singleton or instance to render. Note that you can only add these attributes to specific XML elements (refer to the table above).
|
|
288
|
+
|
|
289
|
+
* `dataCollection`: specifies the collection singleton or instance to bind to the table. This is the name of the model file for singletons or the ID prefixed with the controller symbol ('$') for instances.
|
|
290
|
+
|
|
291
|
+
* `dataTransform`: specifies an optional callback to use to format model attributes. The passed argument is a model and the return value is a modified model as a JSON object.
|
|
292
|
+
|
|
293
|
+
* `dataFilter`: specifies an optional callback to use to filter data in the collection. The passed argument is a collection and the return value is an array of models.
|
|
294
|
+
|
|
295
|
+
* `dataFunction`: set to an arbitrary identifier (name) for a function call. Use this identifier to call a function in the controller to manually update the view. This is not a declared function in the controller. This attribute creates an alias to access the underlying binding function, which is part of the Alloy data-view binding framework.
|
|
296
|
+
|
|
297
|
+
Next, create a repeater object (refer to the table above) and place it inline with the view object with the `dataCollection` attribute, or place it in a separate view and use the `Require` tag to import it.
|
|
298
|
+
|
|
299
|
+
To map model attributes, enclose the attribute with curly brackets or braces ('{' and '}'). You can map more than one attribute to a repeater object's property. For example, to assign the Label.text property to the model's title and author attributes, use this notation: `<Label text="{title} by {author}" />.` For more complex transformations, use the `dataTransform` callback to create a custom attribute.
|
|
300
|
+
|
|
301
|
+
In the controller code of the repeater object, you can use the special variable `$model` to reference the current model being iterated over. This variable is present only in data bound controllers and is a reference to the currently bound model. For example, to get the title attribute of the current model, use `$model.title` to access it.
|
|
302
|
+
|
|
303
|
+
> **⚠️ ⚠️ Warning**
|
|
304
|
+
> **IMPORTANT:** When using Alloy's data binding in a view-controller, you **MUST** call the `$.destroy()` function when closing a controller to prevent potential memory leaks. The `destroy` function unbinds the callbacks created by Alloy when the collection-view syntax is used. For example:
|
|
305
|
+
>
|
|
306
|
+
> ```javascript
|
|
307
|
+
> $.win.addEventListener("close", () => {
|
|
308
|
+
> $.destroy();
|
|
309
|
+
> });
|
|
310
|
+
> ```
|
|
311
|
+
>
|
|
312
|
+
> For global singletons, to properly release them you should also remove event handlers with `off()` and set the reference to null:
|
|
313
|
+
>
|
|
314
|
+
> ```javascript
|
|
315
|
+
> $.win.addEventListener("close", () => {
|
|
316
|
+
> $.destroy();
|
|
317
|
+
> Alloy.Collections.book.off();
|
|
318
|
+
> Alloy.Collections.book = null;
|
|
319
|
+
> });
|
|
320
|
+
> ```
|
|
321
|
+
|
|
322
|
+
#### Collection-View Binding Example
|
|
323
|
+
|
|
324
|
+
The following example demonstrates how to add basic collection-view binding to an application. The example binds a collection of album models to a ScrollableView. In the ScrollableView, each model has its own view, which displays the album cover, title of the album and the artist. The `artist` and `title` attributes are bound to a Label object and the `cover` attribute is bound to an ImageView object.
|
|
325
|
+
|
|
326
|
+
1. Add the `<Collection>` tag as a child of the `<Alloy>` tag.
|
|
327
|
+
|
|
328
|
+
**app/views/index.xml**
|
|
329
|
+
|
|
330
|
+
```xml
|
|
331
|
+
<Alloy>
|
|
332
|
+
<Collection src="album" />
|
|
333
|
+
</Alloy>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
2. Next, add the view object(s) you want to bind the data to. In this example, data will be bound to a ScrollableView object.
|
|
337
|
+
|
|
338
|
+
**app/views/index.xml**
|
|
339
|
+
|
|
340
|
+
```xml
|
|
341
|
+
<Alloy>
|
|
342
|
+
<Collection src="album" />
|
|
343
|
+
<Window backgroundColor="white" onClose="cleanup">
|
|
344
|
+
<ScrollableView></ScrollableView>
|
|
345
|
+
</Window>
|
|
346
|
+
</Alloy>
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
3. Add the `dataCollection` attribute to the appropriate view object. Assign this attribute to the collection you want to use. For a ScrollableView object, add the attribute to the `<ScrollableView>` tag. The element to add the attribute to depends on which view object you want to bind data to.
|
|
350
|
+
|
|
351
|
+
**app/views/index.xml**
|
|
352
|
+
|
|
353
|
+
```xml
|
|
354
|
+
<Alloy>
|
|
355
|
+
<Collection src="album" />
|
|
356
|
+
<Window backgroundColor="white" onClose="cleanup">
|
|
357
|
+
<ScrollableView dataCollection="album"></ScrollableView>
|
|
358
|
+
</Window>
|
|
359
|
+
</Alloy>
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
4. Next, create your repeater object and add model attributes. Enclose the model attributes with curly brackets or braces ('{' and '}'). For a ScrollableView, the repeater object can be a View object with additional children objects. The repeater object depends on which view object you are using.
|
|
363
|
+
|
|
364
|
+
**app/views/index.xml**
|
|
365
|
+
|
|
366
|
+
```xml
|
|
367
|
+
<Alloy>
|
|
368
|
+
<Collection src="album"/>
|
|
369
|
+
<Window backgroundColor="white" onClose="cleanup">
|
|
370
|
+
<ScrollableView dataCollection="album">
|
|
371
|
+
<View layout="vertical">
|
|
372
|
+
<ImageView image="{cover}" />
|
|
373
|
+
<Label text="{title} by {artist}" />
|
|
374
|
+
</View>
|
|
375
|
+
</ScrollableView>
|
|
376
|
+
</Window>
|
|
377
|
+
</Alloy>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
5. In the controller, call the Collection's `fetch()` method to initialize the collection and sync any stored models to the view. Remember to call the `$.destroy()` method when you close the controller to prevent memory leaks.
|
|
381
|
+
|
|
382
|
+
**app/controllers/index.js**
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
$.index.open();
|
|
386
|
+
Alloy.Collections.album.fetch();
|
|
387
|
+
|
|
388
|
+
function cleanup() {
|
|
389
|
+
$.destroy();
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
The application is now setup for basic collection-view binding. When any new data is added to the collection, the ScrollableView will be updated with the new data.
|
|
394
|
+
|
|
395
|
+
#### Model-View Binding
|
|
396
|
+
|
|
397
|
+
To bind a single model to a component, create a global singleton or controller-specific model using the [Model tag](https://titaniumsdk.com/guide/Alloy_Framework/Alloy_Guide/Alloy_Views/Alloy_XML_Markup.html#model-element) in the XML markup of the main view and map the model attribute to the view component. To map the attribute to the view component, prefix the model name or id to the attribute, then enclose it with curly brackets or braces ('{' and '}').
|
|
398
|
+
|
|
399
|
+
To do complex transformations on the model attributes, extend the model prototype with a `transform()` function. It should return the modified model as a JSON object.
|
|
400
|
+
|
|
401
|
+
**app/models/album.js**
|
|
402
|
+
|
|
403
|
+
```javascript
|
|
404
|
+
exports.definition = {
|
|
405
|
+
config: {}, // model definition
|
|
406
|
+
extendModel(Model) {
|
|
407
|
+
_.extend(Model.prototype, {
|
|
408
|
+
transform() {
|
|
409
|
+
const transformed = this.toJSON();
|
|
410
|
+
transformed.artist = transformed.artist.toUpperCase();
|
|
411
|
+
return transformed;
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
return Model;
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
A global singleton instance is a single instance of a particular model that is available for use anywhere in your application. When using global instances, they will be in memory for the duration of your application unless you manually release them. The process of manually releasing them should include:
|
|
420
|
+
|
|
421
|
+
* If any controllers are using data binding that relies on the global instance, they should call their own destroy() function: `$.destroy()`
|
|
422
|
+
* Any other event handlers added to the global instance should be removed with the [off()](http://backbonejs.org/#Events-off) function
|
|
423
|
+
* Set the reference of the model to null: `Alloy.Models.nameOfModel = null;`
|
|
424
|
+
|
|
425
|
+
Note that you need to call the `$.destroy()` function when closing the controller to prevent potential memory leaks. The `destroy` function unbinds the callbacks created by Alloy when the model-view syntax is used.
|
|
426
|
+
|
|
427
|
+
#### Model-View Binding Example
|
|
428
|
+
|
|
429
|
+
The example below demonstrates how to bind a model to view components in the XML markup. Notice that each attribute is prefixed with the model's name and enclosed with braces.
|
|
430
|
+
|
|
431
|
+
```xml
|
|
432
|
+
<Alloy>
|
|
433
|
+
<Model src="settings"/>
|
|
434
|
+
<Window backgroundColor="white" onClose="cleanup">
|
|
435
|
+
<View layout="vertical">
|
|
436
|
+
<Label text="Text Size" />
|
|
437
|
+
<Slider value="{settings.textsize}" max="5" min="1"/>
|
|
438
|
+
<Label text="Bold"/>
|
|
439
|
+
<Switch value="{settings.bold}" />
|
|
440
|
+
<Label text="Italics"/>
|
|
441
|
+
<Switch value="{settings.italics}" />
|
|
442
|
+
</View>
|
|
443
|
+
</Window>
|
|
444
|
+
</Alloy>
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
#### Collection Example
|
|
448
|
+
|
|
449
|
+
The example below demonstrates how to display all book models in the collection by the author Mark Twain. It also demonstrates how to use each of the data binding attributes.
|
|
450
|
+
|
|
451
|
+
**app/views/index.xml**
|
|
452
|
+
|
|
453
|
+
```xml
|
|
454
|
+
<Alloy>
|
|
455
|
+
<Collection src="book" />
|
|
456
|
+
<Window class="container">
|
|
457
|
+
<TableView dataCollection="book"
|
|
458
|
+
dataTransform="transformFunction"
|
|
459
|
+
dataFilter="filterFunction"
|
|
460
|
+
dataFunction="updateUI"
|
|
461
|
+
onDragEnd="refreshTable">
|
|
462
|
+
<!-- Also can use Require -->
|
|
463
|
+
<TableViewRow title="{title}" />
|
|
464
|
+
</TableView>
|
|
465
|
+
</Window>
|
|
466
|
+
</Alloy>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**app/controllers/index.js**
|
|
470
|
+
|
|
471
|
+
```javascript
|
|
472
|
+
$.index.open();
|
|
473
|
+
|
|
474
|
+
// Encase the title attribute in square brackets
|
|
475
|
+
function transformFunction(model) {
|
|
476
|
+
// Need to convert the model to a JSON object
|
|
477
|
+
const transform = model.toJSON();
|
|
478
|
+
transform.title = '[' + transform.title + ']';
|
|
479
|
+
// Example of creating a custom attribute, reference in the view using {custom}
|
|
480
|
+
transform.custom = transform.title + " by " + transform.author;
|
|
481
|
+
return transform;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Show only book models by Mark Twain
|
|
485
|
+
function filterFunction(collection) {
|
|
486
|
+
return collection.where({author:'Mark Twain'});
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function refreshTable(){
|
|
490
|
+
// Trigger the binding function identified by the dataFunction attribute
|
|
491
|
+
updateUI();
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Trigger the synchronization
|
|
495
|
+
const library = Alloy.Collections.book;
|
|
496
|
+
library.fetch();
|
|
497
|
+
|
|
498
|
+
// Free model-view data binding resources when this view-controller closes
|
|
499
|
+
$.index.addEventListener('close', () => {
|
|
500
|
+
$.destroy();
|
|
501
|
+
});
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
As the collection is updated, the view reflects the changes made to the models. If you want to suppress an update, specify `{silent: true}` in the `options` parameters when calling Backbone methods to change model data.
|
|
505
|
+
|
|
262
506
|
### Collection vs Model Data Binding
|
|
263
507
|
|
|
264
|
-
You can bind both a collection of models or an individual model. To bind a model attribute the opening curly bracket is first followed by the model name and then the attribute. To bind a collection you add the `dataCollection` attribute to the container using the collection name as value.
|
|
508
|
+
You can bind both a collection of models or an individual model. To bind a model attribute the opening curly bracket is first followed by the model name and then the attribute. To bind a collection you add the `dataCollection` attribute to the container using the collection name as value. The generated code will then loop over the collection and add the child elements to the container for each model.
|
|
265
509
|
|
|
266
510
|
```xml
|
|
267
511
|
<Alloy>
|
|
@@ -341,9 +585,8 @@ library.on('change:title', e => {
|
|
|
341
585
|
});
|
|
342
586
|
```
|
|
343
587
|
|
|
344
|
-
|
|
345
|
-
This only works if the Backbone method fires the change event and does not enable `{silent: true}` as an option.
|
|
346
|
-
:::
|
|
588
|
+
> **⚠️ ⚠️ Warning**
|
|
589
|
+
> This only works if the Backbone method fires the change event and does not enable `{silent: true}` as an option.
|
|
347
590
|
|
|
348
591
|
If you want to suppress an update, specify `{silent: true}` in the `options` parameters when calling Backbone methods to change model data. The data-bound view will not be updated to reflect the changes.
|
|
349
592
|
|
|
@@ -380,16 +623,6 @@ You can bind models and properties that use names with special characters like d
|
|
|
380
623
|
</Alloy>
|
|
381
624
|
```
|
|
382
625
|
|
|
383
|
-
### Use $.args Values in XML (CLI 7.1.0+)
|
|
384
|
-
|
|
385
|
-
Since CLI 7.1.0, values passed at creation time can be used directly in XML:
|
|
386
|
-
|
|
387
|
-
```xml
|
|
388
|
-
<Alloy>
|
|
389
|
-
<Label text="$.args.foo" />
|
|
390
|
-
</Alloy>
|
|
391
|
-
```
|
|
392
|
-
|
|
393
626
|
### Bind Multiple Models to the Same View
|
|
394
627
|
|
|
395
628
|
You have the ability to bind multiple models to the same view:
|
|
@@ -436,11 +669,12 @@ exports.definition = {
|
|
|
436
669
|
};
|
|
437
670
|
```
|
|
438
671
|
|
|
439
|
-
|
|
440
|
-
The `transform` method must return **all** bound properties, not just the transformed ones. Until Alloy 1.8.1, simple collection data binding did not require this and automatically fell back to the model attributes.
|
|
441
|
-
|
|
672
|
+
> **⚠️ ⚠️ Warning**
|
|
673
|
+
> The `transform` method must return **all** bound properties, not just the transformed ones. Until Alloy 1.8.1, simple collection data binding did not require this and automatically fell back to the model attributes.
|
|
674
|
+
|
|
675
|
+
### Tips and Tricks
|
|
442
676
|
|
|
443
|
-
|
|
677
|
+
#### Lazy Transformation
|
|
444
678
|
|
|
445
679
|
The advantage of defining transformations in the model is that you don't need to repeat them in every controller. A possible disadvantage is that everywhere you bind the model all transformations are computed where you might only need some.
|
|
446
680
|
|
|
@@ -470,7 +704,7 @@ exports.definition = {
|
|
|
470
704
|
};
|
|
471
705
|
```
|
|
472
706
|
|
|
473
|
-
|
|
707
|
+
#### Populating a Model After Data Binding
|
|
474
708
|
|
|
475
709
|
When Alloy compiles your views and controllers, the generated view code precedes your controller code. Any models you define for data binding in the XML will also be created at that point. Just like you call `fetch()` to populate the collection, you do the exact same thing for the model.
|
|
476
710
|
|
|
@@ -495,158 +729,14 @@ $.current.fetch({
|
|
|
495
729
|
$.index.open();
|
|
496
730
|
```
|
|
497
731
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
#### Collection-View Binding
|
|
507
|
-
|
|
508
|
-
To enable collection-view binding, create a global singleton or controller-specific collection using the [Collection tag](https://titaniumsdk.com/guide/Alloy_Framework/Alloy_Guide/Alloy_Views/Alloy_XML_Markup.html#collection-element) in the XML markup of the main view, then add the view object you want to bind data to. The following Titanium view objects support binding to a Collection:
|
|
509
|
-
|
|
510
|
-
| View Object | Since Alloy version | Add data binding attributes to... | Repeater Object to map model attributes to view properties |
|
|
511
|
-
| -------------- | ------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
512
|
-
| ButtonBar | 1.1 | `<Labels>` | `<Label/>` |
|
|
513
|
-
| CoverFlowView | 1.1 | `<Images>` | `<Image/>` |
|
|
514
|
-
| ListView | 1.2 | `<ListSection>` | `<ListItem/>` |
|
|
515
|
-
| Map Module | 1.4 | `<Module module="ti.map" method="createView">` | None, model attributes will be used as params for createAnnotation() directly. |
|
|
516
|
-
| Picker | 1.5 | `<PickerColumn>` or `<Column>` | `<PickerRow/>` or `<Row/>` |
|
|
517
|
-
| ScrollableView | 1.1 | `<ScrollableView>` | `<View/>` May contain children view objects. |
|
|
518
|
-
| TableView | 1.0 | `<TableView>` | `<TableViewRow/>` May contain children view objects. |
|
|
519
|
-
| TabbedBar | 1.1 | `<Labels>` | `<Label/>` |
|
|
520
|
-
| Toolbar | 1.1 | `<Items>` | `<Item/>` |
|
|
521
|
-
| View | 1.0 | `<View>` | Any view object except a top-level container like a Window or TabGroup |
|
|
522
|
-
|
|
523
|
-
You need to specify additional attributes in the markup, which are only specific to collection data binding. The only mandatory attribute is `dataCollection`, which specifies the collection singleton or instance to render. Note that you can only add these attributes to specific XML elements (refer to the table above).
|
|
524
|
-
|
|
525
|
-
* `dataCollection`: specifies the collection singleton or instance to bind to the table. This is the name of the model file for singletons or the ID prefixed with the controller symbol ('$') for instances.
|
|
526
|
-
* `dataTransform`: specifies an optional callback to use to format model attributes. The passed argument is a model and the return value is a modified model as a JSON object.
|
|
527
|
-
* `dataFilter`: specifies an optional callback to use to filter data in the collection. The passed argument is a collection and the return value is an array of models.
|
|
528
|
-
* `dataFunction`: set to an arbitrary identifier (name) for a function call. This is not a declared function in the controller. This attribute creates an alias to access the underlying binding function, which is part of the Alloy data-view binding framework. Use this identifier to call a function in the controller to manually update the view.
|
|
529
|
-
|
|
530
|
-
Next, create a repeater object (refer to the table above) and place it inline with the view object with the `dataCollection` attribute, or place it in a separate view and use the `Require` tag to import it.
|
|
531
|
-
|
|
532
|
-
To map model attributes, enclose the attribute with curly brackets or braces ('{' and '}'). You can map more than one attribute to a repeater object's property. For example, to assign the Label.text property to the model's title and author attributes, use this notation: `<Label text="{title} by {author}" />.` For more complex transformations, use the `dataTransform` callback to create a custom attribute.
|
|
533
|
-
|
|
534
|
-
In the controller code of the repeater object, you can use the special variable `$model` to reference the current model being iterated over. This variable is present only in data bound controllers and is a reference to the currently bound model. For example, to get the title attribute of the current model, use `$model.title` to access it.
|
|
535
|
-
|
|
536
|
-
::: warning ⚠️ Warning
|
|
537
|
-
**IMPORTANT:** When using Alloy's data binding in a view-controller, you **MUST** call the `$.destroy()` function when closing a controller to prevent potential memory leaks. The `destroy` function unbinds the callbacks created by Alloy when the collection-view syntax is used. For example:
|
|
538
|
-
|
|
539
|
-
```
|
|
540
|
-
$.win.addEventListener("close", () => {
|
|
541
|
-
$.destroy();
|
|
542
|
-
});
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
For global singletons, to properly release them you should also remove event handlers with `off()` and set the reference to null:
|
|
546
|
-
|
|
547
|
-
```javascript
|
|
548
|
-
$.win.addEventListener("close", () => {
|
|
549
|
-
$.destroy();
|
|
550
|
-
Alloy.Collections.book.off();
|
|
551
|
-
Alloy.Collections.book = null;
|
|
552
|
-
});
|
|
553
|
-
```
|
|
554
|
-
:::
|
|
555
|
-
|
|
556
|
-
#### Collection-View Binding Example
|
|
557
|
-
|
|
558
|
-
The following example demonstrates how to add basic collection-view binding to an application. The example binds a collection of album models to a ScrollableView. In the ScrollableView, each model has its own view, which displays the album cover, title of the album and the artist. The `artist` and `title` attributes are bound to a Label object and the `cover` attribute is bound to an ImageView object.
|
|
559
|
-
|
|
560
|
-
1. Add the `<Collection>` tag as a child of the `<Alloy>` tag.
|
|
561
|
-
|
|
562
|
-
**app/views/index.xml**
|
|
563
|
-
|
|
564
|
-
```xml
|
|
565
|
-
<Alloy>
|
|
566
|
-
<Collection src="album" />
|
|
567
|
-
</Alloy>
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
2. Next, add the view object(s) you want to bind the data to.
|
|
571
|
-
|
|
572
|
-
**app/views/index.xml**
|
|
573
|
-
|
|
574
|
-
```xml
|
|
575
|
-
<Alloy>
|
|
576
|
-
<Collection src="album" />
|
|
577
|
-
<Window backgroundColor="white" onClose="cleanup">
|
|
578
|
-
<ScrollableView></ScrollableView>
|
|
579
|
-
</Window>
|
|
580
|
-
</Alloy>
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
3. Add the `dataCollection` attribute to the appropriate view object.
|
|
584
|
-
|
|
585
|
-
**app/views/index.xml**
|
|
586
|
-
|
|
587
|
-
```xml
|
|
588
|
-
<Alloy>
|
|
589
|
-
<Collection src="album" />
|
|
590
|
-
<Window backgroundColor="white" onClose="cleanup">
|
|
591
|
-
<ScrollableView dataCollection="album"></ScrollableView>
|
|
592
|
-
</Window>
|
|
593
|
-
</Alloy>
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
4. Next, create your repeater object and add model attributes.
|
|
597
|
-
|
|
598
|
-
**app/views/index.xml**
|
|
599
|
-
|
|
600
|
-
```xml
|
|
601
|
-
<Alloy>
|
|
602
|
-
<Collection src="album"/>
|
|
603
|
-
<Window backgroundColor="white" onClose="cleanup">
|
|
604
|
-
<ScrollableView dataCollection="album">
|
|
605
|
-
<View layout="vertical">
|
|
606
|
-
<ImageView image="{cover}" />
|
|
607
|
-
<Label text="{title} by {artist}" />
|
|
608
|
-
</View>
|
|
609
|
-
</ScrollableView>
|
|
610
|
-
</Window>
|
|
611
|
-
</Alloy>
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
5. In the controller, call the Collection's `fetch()` method to initialize the collection and sync any stored models to the view.
|
|
615
|
-
|
|
616
|
-
**app/controllers/index.js**
|
|
617
|
-
|
|
618
|
-
```javascript
|
|
619
|
-
$.index.open();
|
|
620
|
-
Alloy.Collections.album.fetch();
|
|
621
|
-
|
|
622
|
-
function cleanup() {
|
|
623
|
-
$.destroy();
|
|
624
|
-
}
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
#### Model-View Binding
|
|
628
|
-
|
|
629
|
-
To bind a single model to a component, create a global singleton or controller-specific model using the [Model tag](https://titaniumsdk.com/guide/Alloy_Framework/Alloy_Guide/Alloy_Views/Alloy_XML_Markup.html#model-element) in the XML markup of the main view and map the model attribute to the view component. To map the attribute to the view component, prefix the model name or id to the attribute, then enclose it with curly brackets or braces ('{' and '}').
|
|
630
|
-
|
|
631
|
-
To do complex transformations on the model attributes, extend the model prototype with a `transform()` function. It should return the modified model as a JSON object.
|
|
632
|
-
|
|
633
|
-
**app/models/album.js**
|
|
634
|
-
|
|
635
|
-
```javascript
|
|
636
|
-
exports.definition = {
|
|
637
|
-
config: {}, // model definition
|
|
638
|
-
extendModel(Model) {
|
|
639
|
-
_.extend(Model.prototype, {
|
|
640
|
-
transform() {
|
|
641
|
-
const transformed = this.toJSON();
|
|
642
|
-
transformed.artist = transformed.artist.toUpperCase();
|
|
643
|
-
return transformed;
|
|
644
|
-
}
|
|
645
|
-
});
|
|
646
|
-
return Model;
|
|
647
|
-
}
|
|
648
|
-
};
|
|
649
|
-
```
|
|
732
|
+
> **⚠️ ⚠️ Warning**
|
|
733
|
+
> With the release of CLI 7.1.0, values passed in at creation of a view can be used as values in TSS and XML. For example, if the **foo** property was passed in at creation it can be used on a label:
|
|
734
|
+
>
|
|
735
|
+
> ```xml
|
|
736
|
+
> <Alloy>
|
|
737
|
+
> <Label text="$.args.foo" />
|
|
738
|
+
> </Alloy>
|
|
739
|
+
> ```
|
|
650
740
|
|
|
651
741
|
## Alloy Sync Adapters and Migrations
|
|
652
742
|
|
|
@@ -768,16 +858,16 @@ In Alloy, migrations are defined by JavaScript files located in the `app/migrati
|
|
|
768
858
|
|
|
769
859
|
The migration file contains two functions that need to be implemented: `migration.up(migrator)` and `migration.down(migrator)`, where `migrator` is a special migration object that provides references to the database and table as well as some convenient functions for table operations:
|
|
770
860
|
|
|
771
|
-
| Key | Description
|
|
772
|
-
| ------------- |
|
|
773
|
-
| `db` | Handle to a `Ti.Database` instance. DO NOT CLOSE THIS HANDLE.
|
|
774
|
-
| `dbname` | Name of the database.
|
|
775
|
-
| `table` | Name of the table. Same as value of the `config.adapter.collection_name` key.
|
|
776
|
-
| `idAttribute` | Name of the columns attribute to use as the primary key.
|
|
777
|
-
| `createTable` | Function to create a table. Required parameter is the `columns` object.
|
|
778
|
-
| `dropTable` | Function to drop the current table from the database.
|
|
779
|
-
| `insertRow` | Function to insert data into the table. Useful for preloading data.
|
|
780
|
-
| `deleteRow` | Function to delete data from the table.
|
|
861
|
+
| Key | Description |
|
|
862
|
+
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
863
|
+
| `db` | Handle to a `Ti.Database` instance. Use this handle to execute SQL calls using `db.execute`. DO NOT CLOSE THIS HANDLE OR OPEN A SECOND INSTANCE OF THE DATABASE. |
|
|
864
|
+
| `dbname` | Name of the database. |
|
|
865
|
+
| `table` | Name of the table. Same as value of the `config.adapter.collection_name` key. |
|
|
866
|
+
| `idAttribute` | Name of the columns attribute to use as the primary key. |
|
|
867
|
+
| `createTable` | Function to create a table. Required parameter is the `columns` object. |
|
|
868
|
+
| `dropTable` | Function to drop the current table from the database. |
|
|
869
|
+
| `insertRow` | Function to insert data into the table. Useful for preloading data. |
|
|
870
|
+
| `deleteRow` | Function to delete data from the table. |
|
|
781
871
|
|
|
782
872
|
For example, the migration file below is the initial version of the database that preloads some data in the table.
|
|
783
873
|
|
|
@@ -996,13 +1086,41 @@ To use Backbone 1.1.2 to support Alloy Model and Collections objects, open the p
|
|
|
996
1086
|
|
|
997
1087
|
#### Collection APIs
|
|
998
1088
|
|
|
999
|
-
**Fetch Method Behavior Change**: Backbone Collection objects no longer emit the `reset` event after a `fetch()` call. To use old functionality, pass `{reset: true}` when calling `fetch()` or extend the Collection class
|
|
1089
|
+
**Fetch Method Behavior Change**: Backbone Collection objects no longer emit the `reset` event after a `fetch()` call, which means data-bound views may not update automatically. **This could break existing apps.** To use old functionality, pass `{reset: true}` when calling `fetch()` or extend the Collection class:
|
|
1090
|
+
|
|
1091
|
+
```javascript
|
|
1092
|
+
exports.definition = {
|
|
1093
|
+
config: {
|
|
1094
|
+
// Model configuration
|
|
1095
|
+
},
|
|
1096
|
+
extendModel(Model) {
|
|
1097
|
+
_.extend(Model.prototype, {
|
|
1098
|
+
// extended functions and properties go here
|
|
1099
|
+
});
|
|
1100
|
+
return Model;
|
|
1101
|
+
},
|
|
1102
|
+
extendCollection(Collection) {
|
|
1103
|
+
_.extend(Collection.prototype, {
|
|
1104
|
+
// For Backbone v1.1.2, uncomment the following to override the
|
|
1105
|
+
// fetch method to account for a breaking change in Backbone.
|
|
1106
|
+
/*
|
|
1107
|
+
fetch(options) {
|
|
1108
|
+
options = options ? _.clone(options) : {};
|
|
1109
|
+
options.reset = true;
|
|
1110
|
+
return Backbone.Collection.prototype.fetch.call(this, options);
|
|
1111
|
+
}
|
|
1112
|
+
*/
|
|
1113
|
+
});
|
|
1114
|
+
return Collection;
|
|
1115
|
+
}
|
|
1116
|
+
};
|
|
1117
|
+
```
|
|
1000
1118
|
|
|
1001
1119
|
**New Set Method**: To smartly update the contents of a Collection (adding new models, removing missing ones, and merging those already present), call `set()`.
|
|
1002
1120
|
|
|
1003
1121
|
**Return Value for Methods**: The return values of Collection's `add()`, `push()`, `remove()`, `reset()` and `shift()` methods return the changed model or list of models, instead of `this`.
|
|
1004
1122
|
|
|
1005
|
-
**Add Method**: When invoking `add()` on a collection, passing `{merge: true}` will now cause duplicate models to have their attributes merged in to the existing models.
|
|
1123
|
+
**Add Method**: When invoking `add()` on a collection, passing `{merge: true}` will now cause duplicate models to have their attributes merged in to the existing models. To improve performance, `options.index` will no longer be set in the `add` event callback — use `collection.indexOf(model)` instead.
|
|
1006
1124
|
|
|
1007
1125
|
#### Event APIs
|
|
1008
1126
|
|
|
@@ -1016,6 +1134,9 @@ To use Backbone 1.1.2 to support Alloy Model and Collections objects, open the p
|
|
|
1016
1134
|
|
|
1017
1135
|
**Validation**: Model validation is now only enforced with the `save()` method. Previously, models were also validated with the `set()` method. To force validation when the `set()` method is called, pass `{validate: true}` to the method or extend the Model class. Also, validation now occurs even during 'silent' changes (passing `{silent: true}` to methods). Previously, it would not. Failed validations return the `invalid` event. Previously, a failed model validation would return the `error` event.
|
|
1018
1136
|
|
|
1137
|
+
> **⚠️ ⚠️ Warning**
|
|
1138
|
+
> To validate Model objects, implement the `validate()` method in the `extendModel` key of the model configuration file.
|
|
1139
|
+
|
|
1019
1140
|
**Parse Method**: All `parse` methods now run after a `fetch`. You cannot change the `id` of a model during `parse`. The `parse` method receives `options` as a second parameter.
|
|
1020
1141
|
|
|
1021
1142
|
**Other Changes**:
|
|
@@ -1025,10 +1146,45 @@ To use Backbone 1.1.2 to support Alloy Model and Collections objects, open the p
|
|
|
1025
1146
|
* `url` and `urlRoot` properties may now be passed as options when instantiating a new Model.
|
|
1026
1147
|
* If you want to maintain current models in a collection when using `fetch` the property has changed from `{add:true}` to `{remove:false}`.
|
|
1027
1148
|
|
|
1028
|
-
|
|
1149
|
+
### Parse Method
|
|
1150
|
+
|
|
1151
|
+
After fetching a model or a collection, all defined parse methods will now be run. So fetching a collection and getting back new models could cause both the collection to parse the list, and then each model to be parsed in turn, if you have both methods defined. By default, the parse method is a no-op function that directly passes the JSON response object.
|
|
1152
|
+
|
|
1153
|
+
You are no longer permitted to change the `id` of your model during `parse()`. Use `idAttribute` instead.
|
|
1154
|
+
|
|
1155
|
+
The parse function now receives the `options` dictionary as its second parameter. Previously, it would only be passed a raw `response` object.
|
|
1156
|
+
|
|
1157
|
+
### Silent Option
|
|
1029
1158
|
|
|
1030
1159
|
Passing `{silent:true}` to methods now suppresses the `change:attr` events, thus a data-bound view will not be updated to reflect the changes. The sql sync adapter passed this option by default. It has been updated to no longer pass that option when Backbone 1.1.2 is used (still passed with 0.9.2).
|
|
1031
1160
|
|
|
1161
|
+
If you want the new behavior where `change` events are suppressed, you will need to pass this option or extend the Model or Collection class. The following sample code extends the Model `set()` method by forcing the silent option to true:
|
|
1162
|
+
|
|
1163
|
+
```javascript
|
|
1164
|
+
exports.definition = {
|
|
1165
|
+
config: {
|
|
1166
|
+
// Model configuration
|
|
1167
|
+
},
|
|
1168
|
+
extendModel(Model) {
|
|
1169
|
+
_.extend(Model.prototype, {
|
|
1170
|
+
// Forces silent true option when the model is updated
|
|
1171
|
+
set(attributes, options) {
|
|
1172
|
+
options = options ? _.clone(options) : {};
|
|
1173
|
+
options.silent = true;
|
|
1174
|
+
return Backbone.Model.prototype.set.call(this, attributes, options);
|
|
1175
|
+
}
|
|
1176
|
+
});
|
|
1177
|
+
return Model;
|
|
1178
|
+
},
|
|
1179
|
+
extendCollection(Collection) {
|
|
1180
|
+
_.extend(Collection.prototype, {
|
|
1181
|
+
// extended functions and properties go here
|
|
1182
|
+
});
|
|
1183
|
+
return Collection;
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
```
|
|
1187
|
+
|
|
1032
1188
|
### API Changes
|
|
1033
1189
|
|
|
1034
1190
|
#### New APIs
|
|
@@ -60,7 +60,7 @@ Before using either method, you need to create class styles in the TSS files, ei
|
|
|
60
60
|
}
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
The previous style sheet defines various class and markup element styles for labels, buttons and windows. Alloy assigns a priority for each class, based on its order in the TSS file. Styles listed first receive a lower priority than ones listed afterwards. For example, if both the ldpi and hdpi classes are assigned to a label, since hdpi is after ldpi, the label text is 24 dp not 9 dp.
|
|
63
|
+
The previous style sheet defines various class and markup element styles for labels, buttons and windows. Alloy assigns a priority for each class, based on its order in the TSS file. Styles listed first receive a lower priority than ones listed afterwards. For example, if both the ldpi and hdpi classes are assigned to a label, since hdpi is after ldpi, the label text is 24 dp not 9 dp. Since the Label size of 14 dp is a markup element style and even though it appears after the class styles, it does not have a higher priority number since class styles have higher precedence over markup element styles. The label is still 24 dp not 14 dp. Properties defined inline in the markup and TSS id styles still take precedence over class styles.
|
|
64
64
|
|
|
65
65
|
## Generate a Dynamic Style
|
|
66
66
|
|
|
@@ -158,9 +158,8 @@ Note that code outside of the dialog view-controller is using the instance varia
|
|
|
158
158
|
|
|
159
159
|
To modify the TSS classes of an object that has already been created, use the controller's `addClass`, `removeClass` and `resetClass` methods, which adds, removes or resets the TSS classes of a view object, respectively. As the classes are modified using these API calls, the view is automatically updated. To take advantage of these APIs, you need to enable autostyle for the components or else the view may not update properly.
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
Using the `Require` or `Widget` elements to include external views in a controller-less view does not work with the `updateViews` method — you can include the external views, but the styles cannot be updated.
|
|
163
|
-
:::
|
|
161
|
+
> **⚠️ ⚠️ Warning**
|
|
162
|
+
> Using the `Require` or `Widget` elements to include external views in a controller-less view does not work with the `updateViews` method — you can include the external views, but the styles cannot be updated.
|
|
164
163
|
|
|
165
164
|
Pass a reference to the view object as the first parameter, then pass the classes to add or remove as an array or space-separated string as the second parameter. You can optionally specify inline properties as an optional third parameter.
|
|
166
165
|
|