Intro
We have already seen how to update a template using the update command. And we have also seen reactive dictionaries in action. But in some cases this is not enough.
Take a look at this template:
<ol> <li data-repeat="item items"> <span data-content="item/name">an item name</span>: <span data-content="item/description">an item description</span> </li> </ol>
The javascript code to invoke ZPT-JS:
"use strict"; var zpt = require( 'zpt' ); var dictionary = new zpt.ReactiveDictionary({ items: [ { name: 'John', description: 'The number 1' }, { name: 'Peter', description: 'The number 2' }, { name: 'Luke', description: 'The number 3' } ]; }); // Parse template zpt.run({ root: document.body, dictionary: dictionary });
Now we want to update the list of items. We can set the items in the dictionary this way:
dictionary.items = [ { name: 'John', description: 'The number 1' }, { name: 'Peter', description: 'The number 2' }, { name: 'Luke', description: 'The number 3' }, { name: 'Mary', description: 'The number 4' } ]; );
That code makes ZPT-JS to update the data-repeat node. It removes the current content and rebuilds it all. Perhaps this is not important for you, but it can be.
Anyway this way is not very natural, it would be great if ZPT-JS would provide a way to update the items array and then rebuilds only the needed HTML.
Adding array items
Take a look at this:
zpt.run({ command: 'update', dictionaryActions: [ { id: 'items', action: 'createArray', index: '_last_', newElement: { name: 'Mary', description: 'The number 4' } } ] });
Using dictionaryActions makes it easy to update the dictionary and the template. Some remarks about this:
- The id refers to the variable to modify.
- The action defines the action to run. Available options are createArray, updateArray, deleteArray, updateObject and deleteObject.
- The index indicates the place in the list to add the new element. Available options are '_first_', '_last_' and a numeric value.
- The newElement can be a String, number or object. If it is an array ZPT-JS will add each element of the array, making it easy to add several elements at once.
Updating array items
Now we are going to update the second item (replace Peter by Mia):
zpt.run({ command: 'update', dictionaryActions: [ { id: 'items', action: 'updateArray', index: 1, newElement: { name: 'Mia', description: 'The number 5' } } ] });
Another way would be:
zpt.run({ command: 'update', dictionaryActions: [ { id: 'items', action: 'updateArray', currentElement: { name: 'Peter' }, newElement: { name: 'Mia', description: 'The number 5' } } ] });
Using currentElement provides an alternative way of finding elements to update or delete. The element must match all the fields of the currentElement if it is an object; if it is a literal (numeric or string) it must be equal.
Deleting array items
Now we are going to delete the first item (delete John):
zpt.run({ command: 'update', dictionaryActions: [ { id: 'items', action: 'deleteArray', index: '_first_' } ] });
We could use a 0 value as index.
Another way would be:
zpt.run({ command: 'update', dictionaryActions: [ { id: 'items', action: 'deleteArray', currentElement: { name: 'John' } } ] });
Using searches to define complex expressions
Take a look at this template:
<ol> <li data-repeat="object objectList"> <span data-content="object/id"></span> <ol> <li data-repeat="item object/items"> <span data-content="item/name">an item name</span>: <span data-content="item/description">an item description</span> </li> </ol> </li> </ol>
The javascript code to invoke ZPT-JS:
"use strict"; var zpt = require( 'zpt' ); var dictionary = new zpt.ReactiveDictionary({ objectList: [ { id: 'object1', items: [ { name: 'John', description: 'The number 1' }, { name: 'Peter', description: 'The number 2' }, { name: 'Luke', description: 'The number 3' } ] }, { id: 'object2', items: [ { name: 'Michael', description: 'The number 4' }, { name: 'Chris', description: 'The number 5' }, { name: 'Lars', description: 'The number 6' } ] } ] }); // Parse template zpt.run({ root: document.body, dictionary: dictionary });
Now we want to add a new element to objectList:
zpt.run({ command: 'update', dictionaryActions: [ { id: 'objectList', action: 'createArray', index: '_last_', newElement: { id: 'object3', items: [ { name: 'Mary', description: 'The number 7' }, { name: 'Ann', description: 'The number 8' } ] } } ] });
The resulting HTML looks like this:
1. object1 John: The number 1 Peter: The number 2 Luke: The number 3 2. object2 Michael: The number 4 Chris: The number 5 Lars: The number 6 3. object3 Mary: The number 7 Ann: The number 8
Now we are going to insert a new item inside object3 (Selena, the number 9) to get something like this:
1. object1 John: The number 1 Peter: The number 2 Luke: The number 3 2. object2 Michael: The number 4 Chris: The number 5 Lars: The number 6 3. object3 Selena: The number 9 Mary: The number 7 Ann: The number 8
And the command to run:
zpt.run({ command: 'update', dictionaryActions: [ { search: [ 'objectList', { id: 'object3' }, 'items' ], action: 'createArray', index: '_first_', newElement: { name: 'Selena', description: 'The number 9' } } ] });
A search element is an array of elements that ZPT-JS combines to define a path to access the variable you want to modify. Each element can be one of these types:
- A literal string. Such as objectList or items in this example.
- A literal integer. Useful to select item from arrays.
- An object. ZPT-JS will search into the available items the first that matches it.
In this example the path defined by the search is objectList[ id='object3' ].items.
The same search using an integer as a search item:
zpt.run({ command: 'update', dictionaryActions: [ { search: [ 'objectList', 2, 'items' ], action: 'createArray', index: '_first_', newElement: { name: 'Selena', description: 'The number 9' } } ] });
In this example the path defined by the search is objectList[1].items.
The same search using _last_ as a search item:
zpt.run({ command: 'update', dictionaryActions: [ { search: [ 'objectList', '_last_', 'items' ], action: 'createArray', index: '_first_', newElement: { name: 'Selena', description: 'The number 9' } } ] });
Search elements can be used in any class of dictionaryActions, not only in createArray actions.
Updating object properties
Take a look at this template:
<div> <span data-content="object/name">an item name</span>: <span data-content="object/description">an item description</span> </div>
Now we are going to update the name property (now the name is Dave):
zpt.run({ command: 'update', dictionaryActions: [ { search: [ 'object' ], action: 'updateObject', property: 'name', newElement: 'Dave' } ] });
Deleting object properties
Using the previous template, now we are going to delete the name property:
zpt.run({ command: 'update', dictionaryActions: [ { search: [ 'object' ], action: 'deleteObject', property: 'name' } ] });
The name property has been deleted from the object vaiable in the dictionary.
Using reactive dictionaries
An alternative way of working with dictionary actions is using a reactive dictionary:
"use strict"; var zpt = require( 'zpt' ); var dictionary = new zpt.ReactiveDictionary({ items: [ { id: 'object1', items: [ { name: 'John', description: 'The number 1' }, { name: 'Peter', description: 'The number 2' }, { name: 'Luke', description: 'The number 3' } ] } ]; }); // Parse template zpt.run({ root: document.body, dictionary: dictionary });
To run a dictionary action, you can do this:
dictionary._addActions([ { id: 'items', action: 'createArray', index: '_last_', newElement: { id: 'object2', items: [ { name: 'Sophia', description: 'The number 4' }, { name: 'Jane', description: 'The number 5' }, { name: 'Drew', description: 'The number 6' } ] } } ]);
Be careful, the update is done inmediately. For more details about reactive dictionaries, see reference page