A Store object is the main tool to exchange data with the APS controller.
In this document:
A Store is often used as a data source for multi-entry widgets, for example grid or select.
It is important to remember that a Store object, in contrast with a Model object, does not create a live connection between a widget and data. That is, to reflect data changes in widgets, you need to send an update command explicitly.
In the following example, a grid uses the vpsStore as the data source:
var grid = new Grid({
id: "srv-grid",
store: vpsStore,
...
});
Once the vpsStore store is updated, you can sync it with the grid using the following command:
grid.refresh();
The SDK provides the following kinds of Store:
Resource Store, or simply Store - is actually an interface with the remote data source, that is with the APS controller.
Memory - is the local synchronous store of data. It is not connected to a remote data source.
Store based on the aps/ResourceStore
module is used to interact with a remote APS repository asynchronously.
It can receive, send, remove, and modify data on a remote server through the APS REST API.
The methods of an asynchronous store return promises.
The store completely encapsulates the process of data transfer from and to the remote server.
For the complete list of properties and methods, refer to APS JS API document.
PROPERTY |
TYPE |
DEFAULT |
DESCRIPTION |
---|---|---|---|
|
String presenting the URL of the target data source, that is APS controller |
“” |
Since custom JavaScript files and APS controller are functioning on the same node, its usual value is “/aps/2/resources/” that allows access to all APS resources in the system. This is the only mandatory property. |
|
String presenting APS type |
“” |
Defines the type of APS resources that this store should work with, for example, “”http://aps-standard.org/samples/basic/vps/1.0”. |
|
String |
“aps.type” |
Usually, there is no need to make it different from the default value. It specifies the property used as object identifier. This property is used to reference objects in multi-entry widgets. |
|
“” |
The statement is added to each query request to limit the list of resources or to add data about linked resources. |
The apsType
property specifies a filter based on the implementing()
function and added to the base URL
containing the target
property.
Example:
require(["aps/ResourceStore"],
function(Store){
var vpsStore = new Store({
apsType: "http://aps-standard.org/samples/basic/vps/1.0",
target: "/aps/2/resources/"
});
});
Basing on this definition, you can request a list of objects:
var servers = [];
vpsStore.query().then(function(data) {
servers = data;
});
The above query()
method will generate the following REST request:
GET /aps/2/resources?implementing(http://aps-standard.org/samples/basic/vps/1.0)
Warning
Following this example, it is not allowed to use the apsType
filter, when the target
is
a custom method, for example, target: “/aps/2/resources/” + id + “/myMethod”.
It is possible to add an RQL filter to the store declaration using the baseQuery
property.
For example, to extract the links with other resources, you can assign the select
filter to
the baseQuery
property. In the following code, the linked offer will be available for each requested VPS:
var store = new Store({
apsType: "http://aps-standard.org/samples/basic/vps/2.0",
target: "/aps/2/resources/",
baseQuery: "select(offer)"
});
If the store declared above is used in a grid, the following column will represent offers linked to VPSes:
{ field: "offer.name", name: "Offer" }
To get and modify the store data, you can use the following store methods:
METHOD |
ARGUMENTS |
DESCRIPTION |
---|---|---|
|
object - JSON representation
directives - additional directives of the “dojo/store/api/Store.PutDirectives” type
|
Creates an object or throws an error if the object already exists. |
|
object - JSON representation
directives - additional directives of the “dojo/store/api/Store.PutDirectives” type
|
Configures an object. |
|
ID - APS ID of the resource |
Deletes an object by its APS ID. |
query - a filter containing a list of properties or an RQL string
options - optional arguments used to arrange the result set
|
Queries a store for a set of objects. Both arguments are optional. |
The query(query,options)
method is used to retrieve a list of objects (resources) through the store.
The method returns an object of the dojo/store/api/Store.QueryResults type.
Note
A server response must contain a Content-Range header with the total number of records. See HTTP specification for details .
The most convenient way of processing the returned data is to use array processing methods built into the object.
The query
argument is intended to filter the received data by applying a list of properties
with required values or by applying an RQL string.
Filtering by a list of properties. You can use any properties declared in resource types. In the following example, the method is used to get a list of VPSes where the number of CPU cores is 4.
var store = new Store({
target: "/aps/2/resources/"
});
store.query({ aps:
{ type: "http://aps-standard.org/samples/async1pn/vps/1.0" },
hardware:{ CPU:{ number:4 }}
});
Filtering by means of an RQL request. The following query retrieves a list of VPSes that have not less than 4 CPU cores and whose status is aps:ready:
var vpsStore = new Store({
apsType: "http://aps-standard.org/samples/async1pn/vps/1.0",
target: "/aps/2/resources/"
});
vpsStore.query("hardware.CPU.number=ge=4,aps.status=eq=aps:ready");
The options
argument is an object containing up to three properties:
start[number]
- the number of the first line in the list of queried objects that the method must return.
count[number]
- the number of lines in the returned data block.
sort[array]
- an array of sorting objects. Each object must contain two properties:
attribute
and descending
. The first property contains the name of the
property to be used for sorting, and the second property is a boolean
that requires the sorting direction, for example:
sort[{ attribute:"name", descending:false }]
The mapQuery(row)
method is a custom method that is called from the query
method.
It is used to process a row before the query
method returns it.
The method receives a row, processes it, and then returns it back.
In a Store definition, you can define the custom mapQuery(row)
method if you need to process each
row before the query
method returns it.
Memory based on the aps/Memory module is a local store not connected to any remote data source.
This is the simplest way to create a store. You can simply provide an array to the constructor and work with it using properties and methods similar to those used in the Store.
For the complete list of properties and methods, refer to APS JS API document.
As an example, let us get records filtered by the “prime” property:
require(["aps/Memory", "aps/ready!"],
function(Memory){
var employees = [
{ name: "Jim", department: "accounting", prime: true },
{ name: "Bill", department: "engineering", prime: false },
{ name: "Mike", department: "sales", prime: false },
{ name: "John", department: "sales", prime: true }
];
var store = new Memory({ data: employees, idProperty: "name" });
store.query({ prime: true }).forEach(function(object, i){
console.log("Value of row number " + i, object);
});
In addition, as an argument of the query method, you can use a string
request based on Resource Query Language. A simple aps/Grid
that allows entering
RQL statements in the input field and then implementing them:
load(["aps/PageContainer", [
["aps/Grid", {
id: "grid",
columns: layoutSimpleGrid,
showPaging: false,
store: store
}, [
["aps/Toolbar", [
["aps/TextBox", {
id: "input",
placeHolder: 'RQL query',
// ...
}],
["aps/ToolbarButton", {
id: "button",
label: "Search",
iconClass: "sb-search",
// ...
}],
["aps/ToolbarButton", {
label: "Reset",
iconClass: "sb-show-all",
// ...
}]
]]
]]
]])
You can create new objects in a store, as well as delete existing ones:
employeeStore.add({name:"George", department:"accounting"});
employeeStore.remove("Bill");
You can also change objects located in the store.
The main thing is to not forget to save changes using the put
method.
var jim = employeeStore.get("Jim");
jim.department = "engineering";
employeeStore.put(jim);
Operations with a store can be either synchronous or asynchronous. If you work with a store synchronously, the code must handle the received data immediately after a query is processed. If you work with a store asynchronously, its methods return a promise, and you should use callback functions to handle it.
then
¶You can add such a
handler function using the callback then
method. The method returns a promise that is fulfilled
when the callback completes.
.then(callback, errback, progback);
Parameter |
Type |
Description |
---|---|---|
callback |
Function |
Callback handler of the resolved promise. The request result will be passed to it as an argument. |
errback |
Function |
Callback to be invoked when a promise is rejected. |
progback |
Function |
Callback to be invoked when a promise provides a progress update. |
Example:
store.add({ name: "Tim", department: "R&D", prime: true }).then(function(object) {
// handle created object
});
when
¶The more universal is the dojo/when
module, because the when
method
provided by the module can handle both synchronous and asynchronous
requests. The syntax looks as follows:
when(valueOrPromise, callback, errback, progback);
The parameters of the method are described in the table:
Parameter |
Type |
Description |
---|---|---|
valueOrPromise |
Undefined |
Method or result of calling the method that makes a request. |
callback |
Function |
Callback handler of the request result. The request result will be passed to it as an argument. |
errback |
Function |
Callback to be invoked when a promise is rejected. |
progback |
Function |
Callback to be invoked when a promise provides a progress update. |
The errback and progback arguments are optional.
The following example illustrates the usage of the handler and errback callback functions:
require(["aps/ResourceStore", "dojo/when", "aps/ready!"],
function(Store, when){
var store = new Store({
apsType: "http://aps-standard.org/samples/basic/vps/1.0",
target: "/aps/2/resources/"
});
when(store.query(), function(data) {
console.log("success!", data);
}, function(e){
console.log("error!", e);
});
});
If you send several requests concurrently, the order in which the responses from the server are received will not necessarily match the order in which the requests have been sent. To synchronize processing of the data received as a result of all completed requests, you can use the dojo/promise/all module. With the all method provided by the module, you can combine all requests into a unified call of the when method. In this case, an array with elements representing data from the corresponding requests will be passed to the handler of the request results.
require(["aps/ResourceStore", "dojo/when", "dojo/promise/all", "aps/ready!"],
function(Store, when, all) {
var offerStore = new Store({
apsType: "http://aps-standard.org/samples/offer-mgmt/offer/1.0",
target: "/aps/2/resources/"
});
var vpsStore = new Store({
apsType: "http://aps-standard.org/samples/offer-mgmt/vps/1.0",
target: "/aps/2/resources/"
});
when(all([offerStore.query(), vpsStore.query()]), function(data) {
console.log("success!");
console.log("Offer List", data[0]);
console.log("VPS List", data[1]);
}, function(e) {
console.log("error!", e);
});
});