Offline UI5 Applications

You now have the flexibility to select between local storage or webSQL for your application. In the case of a mobile application, the WebSQL database will be automatically converted to an SQLite database, eliminating any concerns regarding size limitations.

As a Neptune Developer, your primary task is to determine the internal tables and structures that should be stored locally. To assist you in this process, we have developed helpful scripts that streamline the development of offline data handling, making it more convenient and efficient than ever before.

Below, we will describe how Neptune DXP - SAP Edition framework has evolved from a standard web server approach, similar to the one you are familiar with from the SAP Business Server Pages (BSP).

offline ui5 apps 0

The server-side coding used to be often stateful, causing problems with session timeouts and network connection loss. However, after the emergence of SAPUI5 and the implementation of a proper Model-View-Controller framework, we transitioned to a new architecture. In this new architecture, the client handles the state, and only JSON data is exchanged between the server and the client.

offline ui5 apps 1

The structures and internal tables, which are essential for ABAP developers, are now represented as models in the UI5 framework. This enhances the transparency between ABAP and JavaScript, making it easier for developers to comprehend and work with.

offline ui5 apps 2

Since UI5 Models work at runtime, we lose the data when restarting the application. However, in Neptune, you can store UI5 Models offline simply by configuring the appropriate properties on the object.

offline ui5 apps 3

Model Properties

In Neptune Application Designer you can simply enter the type of local cache you want in the attributes of an object bound to SAP data.

  • setCacheGlobal : When set to true - the offline storage will be accessible from other application. Useful for applications sharing same settings etc. The name of the object needs to be the same in all Applications using the global cache

  • setCacheType : Type of offline storage

    • LocalStorage : Only for a small amount of data. Loads faster when starting up the Application

    • WebSQL : For larger dataset. Will be converted to SQLite database for a mobile App.

  • setCacheUserBased : When set to true - the offline storage will use the username as a key field in the database and data will only be visible per user.

  • setEnableCache : When set to true - the offline storage is enabled

  • setInitLoad : Happens when the Application starts the first time

    • Online : Starts an online request to SAP

    • Cache : Loads UI5 Model data from offline storage

    • onlineOnEmptyCache : Loads UI5 Model data from offline storage, but if cache is empty starts an online request to SAP

  • setEnableEncryption : Enables AES256 encryption for the data. The data will always be encrypted in the cache and decrypted when used in runtime and encrypted when storing back to the cache.

Some attributes

offline ui5 apps 4

Neptune Functions

getCache+objectName();

Loads data from offline storage.

setCache+objectName();

Store data to offline storage - Very important when coding offline UI5 Applications, to store data from runtime Model Data to offline

model+objectName

UI5 Model Object - Very important when coding offline UI5 Applications, to access runtime Model Data

ModelData Object

In Neptune’s JavaScript editor, simply right-click to access JavaScript helpers. These helpers consist of pre-made JavaScript and UI5 scripts designed to facilitate JavaScript development. By locating the appropriate object/method you require, it can be effortlessly inserted into your JavaScript editor. All methods for ModelData objects are thoroughly documented.

offline ui5 apps 5

callBack functions will always be executed at the end of the ModelData operation, independently of the results

ModelData.Add

// obj = FieldName of your object with bound model (in the designer)
// objData = new data (must be same structure as the internal table)
// Add Data
ModelData.Add(obj, objData);
// Store to Cache if needed
// Use Neptune function setCache
setCacheobj();

ModelData.AddArray

// obj = FieldName of your object with bound model (in the designer)
// objData = new data (must be same structure as the internal table)
// Add Data
ModelData.Add(obj, objData);
// Store to Cache if needed
// Use Neptune function setCache
setCacheobj();

ModelData.Find

// obj = FieldName of your object with bound model (in the designer)
// keyField = FieldName of your key in the model
// keyValue = FieldValue of your key in the model
// operator = operator for comparison, see full list below
// callBack = callBack function to execute at end of ModelData operation

// Using single key field
var data = ModelData.Find(obj, "keyField", "keyValue", "operator", callBack);

// Using multiple key fields:
// keyFieldArray = Array of FieldNames of your key in the model
// keyValueArray = Array of FieldValues of your key in the model
// operatorArray = Array of operators for comparison, see full list below
var data = ModelData.Find(obj, keyFieldArray, keyValueArray, operatorArray);

// When using arrays, all the conditions have to be met (AND).
// Example - retrieve all employees that have PERNR >= 1035 and ORG_ID == 500000073
var data = ModelData.Find(MasterList, ["PERNR", "ORG_ID"], ["00001035", "50000073"], ["GE", "EQ"]);

// All arrays have to be of the same length!
// exception: Operator can be a single value that will be used for all keyField comparisons

// The data object now contains the array of the found object(s)

// Comparison operators:
// EQ ( default operator, if none is given )
// Contains
// NE
// StartsWith
// EndsWith
// GT
// GE
// LT
// LE
// BT

// Example of BT operator: 1001 <= Plant <= 1005
ModelData.Find(obj,["WERKS"],[["1001","1005"]],"BT");

ModelData.FindDB

// To be used with sap.offline database. Find data from database and move into UI5 model
// field = FieldName of you object with bound model (in the designer)
// obj = data to display
// callBack = callBack function to execute at end of ModelData operation
// In the examples below IT_DD02L is the name of the syncTable

// Contains
var sqlQuery = '%' + inMaterial.getValue() + '%';
ModelData.FindDB(obj, "IT_DD02L", "MATNR LIKE ?", sqlQuery, function() {

// Do stuff then find is completed

});
// Equal
var sqlQuery = inMaterial.getValue();
ModelData.FindDB(obj, "IT_DD02L", "MATNR = ?", sqlQuery, function() {

// Do stuff then find is completed
});

ModelData.Delete

// obj = FieldName of your object with bound model (in the designer)
// keyField = FieldName of your key in the model
// keyValue = FieldValue of your key in the model
// operator = operator for comparison, see full list below

// Using single key field
ModelData.Delete(obj, "keyField", "keyValue", "operator");

// Using multiple key fields:
// keyFieldArray = Array of FieldNames of your key in the model
// keyValueArray = Array of FieldValues of your key in the model
// operatorArray = Array of operators for comparison, see full list below
ModelData.Delete(obj, keyFieldArray, keyValueArray, operatorArray);

// Example
ModelData.Delete(obj, ["keyField_1", "keyField_2"], ["keyValue_1", "keyValue_2"], ["operator_1", "operator_2"]);

// All arrays have to be of the same length!
// exception: Operator can be a single value that will be used for all keyField comparisons

// Matching data entries in the Model will be removed

// Store to Cache if needed
// Use Neptune function setCache
setCacheobj();

// Comparison operators:
// EQ ( default operator, if none is given )
// Contains
// NE
// StartsWith
// EndsWith
// GT
// GE
// LT
// LE
// BT

ModelData.Update

// obj = FieldName of your object with bound model (in the designer)
// keyField = FieldName of your key in the model
// keyValue = FieldValue of your key in the model
// objData = New Data object (structure of the internal table/list)
// operator = operator for comparison, see full list below

// Using single key field
ModelData.Update(obj, "keyField", "keyValue", objData, "operator");

// Using multiple key fields:
// keyFieldArray = Array of FieldNames of your key in the model
// keyValueArray = Array of FieldValues of your key in the model
// operatorArray = Array of operators for comparison, see full list below
ModelData.Update(obj, keyFieldArray, keyValueArray, objData, operatorArray);

// Example
ModelData.Update(obj, ["keyField_1", "keyField_2"], ["keyValue_1", "keyValue_2"], objData, ["operator_1", "operator_2"]);

// KeyField, KeyValue and operator arrays have to be of the same length
// exception: Operator can be single value that will be used for all keyField comparisons
// Matching data entries in the Model will be added or updated

// Store to Cache if needed
// Use Neptune function setCache
setCacheobj();

// Comparison operators:
// EQ ( default operator, if none is given )
// Contains
// NE
// StartsWith
// EndsWith
// GT
// GE
// LT
// LE
// BT

ModelData.UpdateArray

// obj = FieldName of your object with bound model (in the designer)
// keyField = FieldName of your key in the model
// objArray = Array of new Data objects (structure of the internal table/list)
// operator = operator for comparison, see full list below

// Using single key field
ModelData.UpdateArray(obj, "keyField", objArray, "operator");

// Using multiple key fields:
// keyFieldArray = Array of FieldNames of your key in the model
// operatorArray = Array of operators for comparison, see full list below
ModelData.UpdateArray(obj, keyFieldArray, objArray, operatorArray);

// Example
ModelData.UpdateArray(obj, ["keyField_1", "keyField_2"], objArray, ["operator_1", "operator_2"]);

// KeyField and operator arrays have to be of the same length!
// exception: Operator can be single value that will be used for all keyField comparisons

// Matching data entries in the Model will be added or updated
// Store to Cache if needed
// Use Neptune function setCache
setCacheobj();

// Comparison operators:
// EQ ( default operator, if none is given )
// Contains
// NE
// StartsWith
// EndsWith
// GT
// GE
// LT
// LE
// BT

ModelData.UpdateField

// obj = FieldName of your object with bound model (in the designer)
// keyField = FieldName of your key in the model
// keyValue = FieldValue of your key in the model
// updField = FieldName of your update field in the model
// updValue = FieldValue of your update field in the model
// operator = operator for comparison, see full list below

// Using single key field
ModelData.UpdateField(obj, "keyField", "keyValue", "updField", "updValue", "operator");

// Using multiple key fields:
// keyFieldArray = Array of FieldNames of your key in the model
// keyValueArray = Array of FieldValues of your key in the model
// operatorArray = Array of operators for comparison, see full list below
ModelData.UpdateField(obj, keyFieldArray, keyValueArray, "updField", "updValue", operatorArray);

// Example
ModelData.UpdateField(obj, ["keyField_1", "keyField_2"], ["keyValue_1", "keyValue_2"], "updField",
"updValue", ["operator_1", "operator_2"]);

// KeyField, KeyValue and operator arrays have to be of the same length!
// exception: Operator can be single value that will be used for all keyField comparisons

// Using multiple update fields:
// updFieldArray = Array of FieldNames of your update fields in the model
// updValueArray = Array of FieldValues of your update fields in the model
ModelData.UpdateField(obj, "keyField", "keyValue", ["updField_1", "updField_2"], ["updValue_1", "updValue_2"], operatorArray);

// Example
ModelData.UpdateField(obj, "keyField", "keyValue", ["updField_1", "updField_2"], ["updValue_1", "updValue_2"], operator);

// UpdateField, UpdateValue and operator arrays have to be of the same length!

// Array options for key/operator and update parameters can be combined

// Matching data entries in the Model will be updated

// Store to Cache if needed
// Use Neptune function setCache
setCacheobj();

// Comparison operators:
// EQ ( default operator, if none is given )
// Contains
// NE
// StartsWith
// EndsWith
// GT
// GE
// LT
// LE
// BT