...
Code Block |
---|
var retval = plugins.mobileservice.createOfflineDataDescription('data_');
|
Note: the argument is optional and is used to call rest endpoints for row data at forms starting with this prefix
The next step is determining what related data should be traversed and sent to the client. By default (since Servoy 7.2) any relations that exist in a "Mobile Shared Module" attached to the "Mobile Service Solution" will be included in the traversal.
Alternatively, if you provide a list of relation names to include, this will override the inclusion of the relations contained in the "Mobile Shared Module", and only include those relations that you specify.
Code Block |
---|
var traverse = new Array(); traverse.push([ 'accountmanager_to_companies'); traverse.push(, 'companies_to_contacts'); ] |
Lastly we have instruct the OfflineDataDescription to collect the data, starting with root foundset (containing records) and return.
Code Block |
---|
retval.addFoundSet(fs_contact, traverse); return retval; |
Basically addFoundSet in the service solution exposes an unrelated foundset to the mobile client, which can be used in an unrelated way like in a (first) form or databaseManager.getFoundset(...)
For each record in the provided (unrelated) foundset the specified relations are traversed and all data taken.
...
Code Block |
---|
function ws_authenticate(useruid, password) { //TODO find user and check password against pwhash column if (password === 'demo') { //static demo check return { var retval = new Object(); retval.username = useruid;username: useruid return} retval; } return false; } |
In the ws_read method we can utilize the authenticate username variable via
Code Block |
---|
var authenticate_info = questionParams.ws_authenticate[0]; globals.username = authenticate_info.username; |
Here the authenticate username is put into a global variable which in turn can be used like:
Code Block |
---|
//prepare personal data var fs_contact = globals.contact_data$username; //global related foundset using username global var, containing theto account manager contact record |
Full ws_read method for personalized data.
Code Block |
---|
function ws_read(version,name) { var questionParams = arguments[arguments.length-1]; //create return value var retval = plugins.mobileservice.createOfflineDataDescription('data_'); //setting the key for user_select relation var authenticate_info = questionParams.ws_authenticate[0]; globals.username = authenticate_info.username; //prepare personal data var fs_contact = globals.contact_data$username; //global related foundset using username global var, containing the to account manager contact /** * @type {Array<String>} */ record var traverse = new Array(); traverse.push([ 'accountmanager_to_companies');, traverse.push( 'companies_to_contacts'); ] retval.addFoundSet(fs_contact, traverse); return retval; } |
...
Code Block |
---|
function ws_read(version, method) { var questionParams = arguments[arguments.length-1]; if (method == 'list') { /** * @type {String} */ var ids = questionParams.ids[0]; if (ids != null && ids != '') { var idsa = ids.split(',', -1); if (idsa.length > 0) { var json = plugins.mobileservice.getRowDescriptions(foundset.getDataSource(), idsa) return json; } } } throw 404; } |
TIP: since ws_read for entities is likely the same, it might be beneficial to create a base form containing this logic and extend from this form
...
Code Block |
---|
function ws_update(data, version, pk) { if (foundset.find()) { foundset.contact_id = pk; var count = foundset.search(); if (count > 0) { var rec = foundset.getRecord(1); databaseManager.copyMatchingFields(data,rec,true); databaseManager.saveData(rec); } } } |
ws_create is called for new records on the mobile client, example code:
Code Block |
---|
function ws_create(data, version, pk) { var rec = foundset.getRecord(foundset.newRecord()); databaseManager.copyMatchingFields(data,rec,true); databaseManager.saveData(rec); } |
Note: the retrieved PK (and derived FK's) is always UUID's if the underlaying datamodel is not UUID based, keep and apply a mapping!
...
Code Block |
---|
function ws_delete(version, pk) { if (foundset.find()) { var table = databaseManager.getTable(controller.getDataSource()); var pkname = table.getRowIdentifierColumnNames()[0] foundset[pkname] = pk; var count = foundset.search(); if (count > 0) { var rec = foundset.getRecord(1); foundset.deleteRecord(rec); } } } |
...
Code Block |
---|
function ws_update(data, version, authenticateResult) { try { databaseManager.startTransaction(); plugins.mobileservice.performSync(data, version, authenticateResult); databaseManager.commitTransaction(); } catch (e) { databaseManager.rollbackTransaction(); // log the error and return false to that the mobile client will know the sync did fail. application.output(e, LOGGINGLEVEL.ERROR); return false; } } |
This code above starts a transaction then calls the performSync method of the mobile service plugin. This plugin will dispatch all the changes to the various ws_update/create/delete methods of the entity forms. If something goes wrong then an exception will be thrown and the transaction will rollback.
...