Array Data Provider (Legacy)

The built-in legacy array data provider could be bound to collection components in previous versions. It should not be used in new applications.

This legacy built-in type is a data provider implementation based on the JET oj.ArrayDataProvider implementation, where the data is static. A static source of data can be fetched from a backend service, but it is assumed that it does not change frequently and only allows infrequent adds/updates and removes. This data provider can be bound to collection components such as listView and table components. Operations on the data, such as sorts, adds, removes, or updates are managed by the vb/ArrayDataProvider itself. This is different from the vb/ServiceDataProvider, where all operations generally are processed in the back end via REST calls.

New applications should use vb/ArrayDataProvider2.

The ArrayDataProvider behaves as follows:

  • Writes to individual properties of the ArrayDataProvider.data are allowed. Usually this happens when components use writable binding expressions that write directly to properties within individual data (array) items.

    Note:

    It's important to remember that when you use a writable binding expression, the component writes the new value to the bound ADP.data property. This causes the ADP variable to change and the table or listview component bound to the ADP variable to refresh. If this behavior is not desired, use vb/ArrayDataProvider2 and the proper editable table / list-view patterns. (The recommended patterns are documented in the Oracle blogs.)
  • ArrayDataProvider does not support using the fireDataProviderEventAction to mutate data. Instead, use the assignVariablesAction.

A variable of this type is generally defined on the page, using the built-in type vb/ArrayDataProvider.

{
 
  "variables": {
    "productListADPD": {
      "type": "vb/ArrayDataProvider",
      "defaultValue": {
        "itemType": "application:productSummary"
      }
    }
  }
  ...

The ArrayDataProvider has several properties available.

data

The static array of data that the ArrayData Provider wraps. The data property is set once when the page or component loads. The implicitSort criteria that the data is pre-sorted with is also set once the page or component loads.

idAttribute

A string or array of string field names that represent the primary key for each row. Deprecated: use keyAttributes instead.

keyAttributes

A string or array of string field names that represent the primary key for each row.

  • a field name - the key value is a primitive or whatever the field value represents.

  • an array of field names - the key will also be an array of values.

  • @value, use all properties - the key will also be an array of all values.

  • @index, use the index as the key - the key will be an integer.

implicitSort

The implicit sort criteria by which the data is pre-sorted. This is an array of objects, where each object is an atomic sort expression of the form:

{
  "attribute": "<name of the field>", 
  "direction": "<'ascending' (default) or 'descending'>" 
}

itemType

The type of each item in the data array. This is usually a string that points to an application type or to a definition.

Features and Capabilities

The ArrayDataProvider provides a sort feature:

  • {capabilityName: 'full', attributes: 'multiple} means the endpoint has support for sorting results by one or more fields.

  • null means the endpoint has no support for sorting.

Data Mutation and Refresh Events

vb/ArrayDataProvider notifies components when the underlying data mutates or is changed in a way that requires a refresh. The only way to mutate ArrayDataProvider data is via the 'assignVariablesAction' event. The 'fireDataProviderEventAction' is a no-op when it comes to updating the data property but can be used to notify just the listeners of the ArrayDataProvider (components) of the change. But the latter is not needed when assignVariablesAction is used, because it does both.

Variable Events

All variables including vb/ArrayDataProvider raise the variable onValueChanged event when any of its properties change. ArrayDataProvider in particular will detect which of its data has changed, and will automatically notify subscribers of just the change (these are typically components that are bound to the ArrayDataProvider variable and have registered a listener).

Assigning Data

The data property of the vb/ArrayDataProvider variable is set once, when the page or component loads. The implicitSort criteria that the data is pre-sorted with is also set once the page or component loads.

After the initial load, a page author can mutate the data by directly manipulating the data array using the assignVariablesAction action. Typically, the mutation to the data is triggered by the UI or some other application logic. In either circumstance, the ArrayDataProvider data needs to be manually updated. When the data property mutates, ArrayDataProvider automatically detects the change and notifies all listeners/components of the change, so that they can re-render. If the data is mutated directly, it's not required to use the fireDataProviderEvent action with the ArrayDataProvider.

Example 1-10 Where the data refers to a constant

Here the ArrayDataProvider variable productADPE gets its initial data from a constant, productsConstant. The ArrayDataProvider data array is initialized with one item.

"constants": {
  "productsConstant": {
    "type": "ProductType[]",
    "defaultValue": [{
      "Amount": 10,
      "CurrencyCode": "USD",
      "Quantity": 1,
      "RegisteredPrice": 10,
      "Type": "Constant",
      "Product": "Product-C1",
      "id": 10
    }]
  }
},
"productsADPE": {
  "type": "vb/ArrayDataProvider",
  "description": "mutations on data have to be done directly to the 'data' property",
  "defaultValue": {
    "data": "{{ $page.constants.productsConstant }}",
    "itemType": "ProductType",
    "keyAttributes": "id"
  }
},

In order to add a new item to the above ArrayDataProvider data you can use an assignVariablesAction:

  • Line 12: action that generates a new product item
  • Line 22: assigns a new array with the new item appended to the existing data

It is currently not possible to add to a specific index of the array using assignVariablesAction, when the array references a constants expression.

 1 "addProductsADPE": {
 2  "description": "adds the generated product to the end",
 3  "variables": {
 4    "detail": {
 5      "required": true,
 6      "type": "any",
 7      "input": "fromCaller"
 8    }
 9  },
10  "root": "generateNewProduct",
11  "actions": {
12    "generateNewProduct": {
13      "module": "vb/action/builtin/callModuleFunctionAction",
14      "parameters": {
15        "module": "{{ $page.functions }}",
16        "functionName": "generateNewProduct"
17      },
18      "outcomes": {
19        "success": "assignToADPData"
20      }
21    },
22    "assignToADPData": {
23      "module": "vb/action/builtin/assignVariablesAction",
24      "parameters": {
25        "$page.variables.productsADPE.data": {
26          "source": "{{ $page.variables.productsADPE.data.concat([$chain.results.generateNewProduct]) }}",
27          "reset": "empty"
28        }
29      }
30    }
31  }
32 }

Example 1-11 Where the data refers to another variable

In this example the ArrayDataProvider variable productADPF gets its initial data from the variable products. The ArrayDataProvider data array is initialized with one item.

"variables": {
  "products": {
    "type": "ProductType[]",
    "defaultValue": [{
      "Amount": 20,
      "CurrencyCode": "USD",
      "Quantity": 2,
      "RegisteredPrice": 20,
      "Type": "Variable",
      "Product": "Product-V1",
      "id": 20
    }]
  },
  "productsADPF": {
    "type": "vb/ArrayDataProvider",
    "description": "mutations on data can be done on the referenced 'products' or "
     + "on the 'data' property directly. The latter will disconnect the reference",
    "defaultValue": {
      "data": "{{ $page.variables.products }}",
      "itemType": "ProductType",
      "keyAttributes": "id"
    }
  },

In order to update an item of the above ArrayDataProvider data, you can use an assignVariablesAction:

  • Line 5: the action chain gets the updated product item
  • Line 22: assign a new array to productsADPF with the updated product
 1 "updateProductsADPF": {
 2  "root": "assignToADPData",
 3  "description": "",
 4  "variables": {
 5    "updatedProduct": {
 6      "type": "page:ProductType",
 7      "required": true,
 8      "input": "fromCaller"
 9    },
10    "key": {
11      "type": "number",
12      "required": true,
13      "input": "fromCaller"
14    }
15  },
16  "actions": {
17    "assignToADPData": {
18      "module": "vb/action/builtin/assignVariablesAction",
19      "description": "assigning to specific item in ADP.data is not possible, so we replace entire array",
20      "parameters": {
21        "$page.variables.productsADPF.data": {
22          "source": "{{ $page.variables.productsADPF.data.map(p => (p.id === $chain.variables.key ? $chain.variables.updatedProduct : p)) }}",
23          "reset": "empty"
24        }
25      }
26    }
27  }
28}

Example 1-12 Where the data is literally inlined

In this example the ArrayDataProvider variable productADPG has its initial data inlined.

"variables": {
  "productsADPG": {
    "type": "vb/ArrayDataProvider",
    "description": "any mutations are done on 'data' property directly",
    "defaultValue": {
      "itemType": "ProductType",
      "keyAttributes": "id",
      "data": [{
        "Amount": 30,
        "CurrencyCode": "USD",
        "Quantity": 3,
        "RegisteredPrice": 30,
        "Type": "Literal",
        "Product": "Product-Literal",
        "id": 30
      }]
    }
  }
}

In order to remove an item from the above ArrayDataProvider data you can use an assignVariablesAction. Line 16 filters the data array of productsADPG by removing the item with the matching key.

 1 "removeProductsADPG": {
 2   "root": "removeFromProductsADPG",
 3   "description": "",
 4   "variables": {
 5     "key": {
 6       "type": "number",
 7       "required": true,
 8       "input": "fromCaller"
 9     }
10   },
11   "actions": {
12     "removeFromProductsADPG": {
13       "module": "vb/action/builtin/assignVariablesAction",
14       "description": "splice returns the removed item, so filter is used instead, which mutates and returns the original array",
15       "parameters": {
16         "$page.variables.productsADPG.data": {
17           "source": "{{ $page.variables.productsADPG.data.filter((p) => p.id !== $chain.variables.key) }}",
18           "reset": "empty",
19           "auto": "always"
20         }
21       }
22     }
23   }
24 }

When the data property is a literal value, to add or update items to the array it is possible to assign to a specific item of the array:

  • Line 1: shows an example action where the product is updated directly
  • Line 12: shows an example action where the new product is added to the tail end of the data array
 1 "updateProductsADPG": {
 2   "module": "vb/action/builtin/assignVariablesAction",
 3   "description": "directly updating ADP.data item is possible when data has no expression",
 4   "parameters": {
 5     "$page.variables.productsADPG.data[$page.variables.productsADP3.data.findIndex(p => p.id === $chain.variables.key)]": {
 6       "source": "{{ $chain.variables.product }}",
 7       "auto": "always",
 8       "reset": "empty"
 9     }
10   }
11 }
12 "addToProductsADPGTail": {
13   "module": "vb/action/builtin/assignVariablesAction",
14   "parameters": {
15   "$page.variables.productsADPG.data[$page.variables.productsADPG.data.length]": {
16       "source": "{{ $chain.results.generateNewProduct }}"
17     }
18   }
19 }