sapui5 batch with sap.ui.model.odata.v2.ODataModel - odata

I created table with data using JSONModel
var oModel = new sap.ui.model.json.JSONModel(query);
oTablePrio = sap.ui.getCore().getControl("idTablePrio2");
oTablePrio.setModel(oModel, "Prio2");
Everythink look and work good.
Now i have added new column(prio) where i will change value. After changing i would like to save every rows( in the SAP ztable ) after clicking buton save .
I made something like this
var oModel = new sap.ui.model.odata.v2.ODataModel(gServiceUrl);
oModel.setUseBatch(true);
for (var i = 0; i < data.length; i++) {
sEntry.Matnr = data[i].Matnr;
sEntry.Bbynr = data[i].Bbynr;
sEntry.Prio = data[i].Prio;
oModel.update("/WielosztSet('"+data[i].Bbynr+"')", sEntry, {
method: "PUT", function(){
alert('Data Updated Successfully');
location.reload(true);
},function(){
sap.m.MessageToast.show('Update failed',{duration:1000});
}});
}
Now only it sends data only with the last row.
I wrote that i cannot update more than one row in this way and I need to make batch.
I connot find how to create working batch for uploding data with sap.ui.model.odata.v2.ODataModel
Please give me some advice.

Before the call of the oModel.update assign the UseBatch to true:
oModel.setUseBatch(true);
Make your for:
for (var i = 0; i < data.length; i++) {
sEntry.Matnr = data[i].Matnr;
sEntry.Bbynr = data[i].Bbynr;
sEntry.Prio = data[i].Prio;
oModel.update("/WielosztSet('"+data[i].Bbynr+"')", sEntry, {
method: "PUT", function(){
alert('Data Updated Successfully');
location.reload(true);
},function(){
sap.m.MessageToast.show('Update failed',{duration:1000});
}});
}
At the end of for put the submitChanges.
oModel.submitChanges();
oModel.setUseBatch(false); // Make false if you reuse this oModel.
Regards.

Related

Looping through custom fields to populate dynamic fields in Zapier

I'm not sure how to loop through the custom fields when adding a dynamic field via the web script editor.
When I test I can see the fields are being returned in the console
Where the number of fields is different with each instance of our app.
This is the code I'm using to return the data.
return z.request(options)
.then((response) => {
response.throwForStatus();
const results = z.JSON.parse(response.content)._embedded;
return results;
});
I assume I need to loop through each of the fields, pull out the ID and name and then put them back as an array of objects?
Something like this, only problem is nothing is being returned?
return z.request(options)
.then((response) => {
response.throwForStatus();
const results = z.JSON.parse(response.content).results._embedded;
var cFields = [];
for (var i = 0; i < results.length; i++) {
cFields.push({'id': results.customFields[i].label});
}
return cFields;
});
Any pointers?
I worked this out in the end. I think the problem was more because of my lack of coding knowledge. Not sure if this is the best answer but it worked.
return z.request(options)
.then((response) => {
response.throwForStatus();
const results = z.JSON.parse(response.content)._embedded;
let customFields = [];
for (let i = 0; i < results.customFields.length; i++) {
let customFieldsObj = {};
customFieldsObj['key'] = results.customFields[i].id;
customFieldsObj['label'] = results.customFields[i].label;
let helpText = results.customFields[i].type + ' Field';
customFieldsObj['helpText'] = helpText.toUpperCase();
customFields.push(customFieldsObj);
}
return customFields;
});

SAPUI5 oData.V2 How to invoke a function after everything in a batch request is done?

I have an issue while making an SAPUI5 odata V2 batch request :
var that = this;
var oServiceModel = that.getModel("oServiceModel");
odataMod = this.getModel("Service");
odataMod.setUseBatch(true);
var aData = oServiceModel.getData();
var stupidService = _.filter(aData, function (ae) {
return ae.Info === "-N/A";
});
var i = 0 ;
_.forEach(stupidService, function (sap) {
oGlobalBusyDialog.setText("Deleting service :" + sap.ObjectID);
oGlobalBusyDialog.setTitle("Deleting Service");
oGlobalBusyDialog.open();
that.removeService(sap).then(function () {
if (i === 615) {
oGlobalBusyDialog.close();
}
}).catch(function () {});
});
my Delete function is like this:
removeService: function (service) {
var that = this;
return new Promise(
function (resolve, reject) {
odataMod.remove('/ProjectTaskServiceCollection(\'' + service.ObjectID + '\')/', {
success: function (oData) {
resolve(oData);
},
error: function (oResult) {
that.handleError(oResult);
oGlobalBusyDialog.close();
reject(oResult);
}
});
});
What's happening ,is that if I'm trying to delete 500 entry, and if 200 entry cannot be deleted, the error message gets displayed 200 times
How to make it in a way to only display the error message once ?
Also, I want to turn off the batch request once everything is done odataMod.setUseBatch(false); how to do it ?
*EDIT: *
I've manage to do :
var aDeffGroup = odataMod.getDeferredGroups();
//add your deffered group
aDeffGroup.push("deletionGroup");
for (var s = 0; s < 5; s++) {
odataMod.remove('/ProjectTaskServiceCollection(\'' + stupidService[s].ObjectID + '\')/', {
//pass groupid to remove method.
groupId: "deletionGroup"
});
}
odataMod.submitChanges({
// your deffered group id
groupId: "deletionGroup",
success: function() {
//Get message model data from Core and it contains all errors
// Use this data to show in dialog or in a popover or set this to your local model see below code
var aErrorData = sap.ui.getCore().getMessageManager().getMessageModel();
console.log(aErrorData);
}
});
yet stills my console.log(aErrorData); still prints multiple error message
Instead of doing individual deletion odata calls. Add these all remove methods in a single group, then call odatamod.submitChanges() method.
Example:
//get all deffered groups
var aDeffGroup = odataMod.getDeferredGroups();
//add your deffered group
aDeffGroup.push("deletionGroup");
//set it back again to odatamodel
odataMod.setDeferredGroups(aDeffGroup);
odataMod.remove('/ProjectTaskServiceCollection(\'' + service.ObjectID + '\')/', {
//pass groupid to remove method.
groupId: "deletionGroup"});
odataMod.submitChanges({
// your deffered group id
groupId:"deletionGroup",
success: function() {
//Get message model data from Core and it contains all errors
// Use this data to show in dialog or in a popover or set this to your local model see below code
var aErrorData = sap.ui.getCore().getMessageManager().getMessageModel();
});

Creating chat "rooms" using Node, Express, Heroku, and Socket.io

So I've been building an app for quite some time and I'm running into problems in terms of scalability. I'm new to Node, and Heroku for that matter. Please bear with me.
I originally followed this tutorial to get my node service up and running. Essentially, it creates a real-time chat service. However, my question now comes with creating 'rooms'. It doesn't make sense to me that I might have 15+ chats going on, yet they all are calling the same functions on the same clientSocket, and I have to determine what UI updates go to which clients on the front end. As of now, I have upwards of 15 clients all trying to interact on different chats, but I'm pushing updates to everyone at once (for example, when a message is posted), then determining who's UI to update based on which room ID I'm cacheing on each device. Seems like a terrible waste of computing power to me.
I'm thinking that the solution involves modifying how each client connects (which is the code snippet below). Is there a way to create location based 'rooms', for example, where the clients connected are the only ones getting those updates? Any idea how to go about this solution? If anyone is also willing to just explain what I'm not understanding about Node, Express, Heroku, Socket.io or others, please do let me know.
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var pg = require('pg');
var userList = [];
var typingUsers = {};
var ActiveQueue = [];
app.get('/', function(req, res){
res.send('<h1>Active RT Queue</h1>');
});
var conString = "postgres://url";
pg.defaults.ssl = true;
var client = new pg.Client(conString);
client.connect(function(err) {
if(err) {
return console.error('could not connect to postgres', err);
}
});
http.listen(process.env.PORT || 5000, function(){
console.log('Listening on *:5000');
});
io.on('connection', function(clientSocket){
console.log('a user connected');
clientSocket.on('disconnect', function(){
console.log('user disconnected');
var clientNickname;
for (var i=0; i<userList.length; i++) {
if (userList[i]["id"] == clientSocket.id) {
userList[i]["isConnected"] = false;
clientNickname = userList[i]["nickname"];
break;
}
}
delete typingUsers[clientNickname];
io.emit("userList", userList);
//io.emit("userExitUpdate", clientNickname);
//io.emit("userTypingUpdate", typingUsers);
});
clientSocket.on("exitUser", function(clientNickname){
for (var i=0; i<userList.length; i++) {
if (userList[i]["id"] == clientSocket.id) {
userList.splice(i, 1);
break;
}
}
io.emit("userExitUpdate", clientNickname);
});
clientSocket.on("connectUser", function(clientNickname) {
var message = "User " + clientNickname + " was connected.";
console.log(message);
var userInfo = {};
var foundUser = false;
for (var i=0; i<userList.length; i++) {
if (userList[i]["nickname"] == clientNickname) {
userList[i]["isConnected"] = true
userList[i]["id"] = clientSocket.id;
userInfo = userList[i];
foundUser = true;
break;
}
}
if (!foundUser) {
userInfo["id"] = clientSocket.id;
userInfo["nickname"] = clientNickname;
userInfo["isConnected"] = true
userList.push(userInfo);
}
io.emit("userList", userList);
io.emit("userConnectUpdate", userInfo)
});
///functions pertaining to transfer of messages and updating the UI follow
I would try something like this:
io.on('connection', function(clientSocket) {
clientSocket.on('room:general', function(data) {
var user = data.user;
var message = data.message;
console.log('%s sent new message: %s',user,message);
io.emit('room:general:newMessage', data);
});
//and so for each room
.........
});
and from front end you need to send JSONObject:
{
user:your_username,
message:user_message
}
,
socket.emit("room:general", json_object);
socket.on("room:general:newMessage", onYourDefinedEmiterListener);
..........
..........
//and so for each room
I never made Chat Application, hope it helps.

How save multiple values JSONStore

I need to replace multiple value in JSONStore of IBM Worklight.
In this way is saved only first value. Why?
.then(function() {
for (var index = 0; index < elencoSpese.length; index++) {
var spesa = elencoSpese[index];
var spesaReplace = {_id: spesa.id, json: spesa};
spesa.id_nota_spesa = idNotaSpesa;
spesa.checked = true;
WL.JSONStore.get(COLLECTION_NAME_SPESE).replace(spesaReplace);
}
})
You want to build an array of JSONStore documents and pass it to the replaceAPI. For example:
.then(function() {
var replacementsArray = [];
for (var index = 0; index < elencoSpese.length; index++) {
var spesa = elencoSpese[index];
var spesaReplace = {_id: spesa.id, json: spesa};
spesa.id_nota_spesa = idNotaSpesa;
spesa.checked = true;
replacementsArray.push(spesaReplace);
}
return WL.JSONStore.get(COLLECTION_NAME_SPESE).replace(replacementsArray);
})
.then(function (numOfDocsReplaced) {
// numOfDocsReplaced should equal elencoSpese.length
})
I assume this happens in the JavaScript implementation of the JSONStore API, if that's the case the answer is in the documentation here. The JavaScript implementation of JSONStore expects code to be called serially. Wait for an operation to finish before you call the next one. When you call the replace multiple times without waiting, you're calling the API in parallel instead of serially. This should not be an issue in the production environments (i.e. Android, iOS, WP8 and W8).

Insert Element procedure error occured in Jquery

I have the following HTML code:
<table class="viewTable">
<tr>
<td>Price</td>
</tr>
</table>
and I want to insert data dynamically using Javascript as follows:
var totalPrice = 0;
map.each(function(key , value , i) {
params = {};
params.id = key;
// get datas from Controller class via ajax
ajax(url, params, false, function(result) {
totalPrice += setData(result , key , value);
});
});
// alert("something!"); // this may satisfy my problem.. I have no idea..
// Total Price shown on last row
$('table.viewTable tr:last').after("<tr class='title_bar'><td colspan='5' style='text-align: right;padding-right: 35px;'>"+num2Currency(totalPrice)+"</td></tr>");
The setData function is:
function setData(result , partsId , count) {
var price = result.price;
html = [];
html.push("<tr>");
html.push("<td><div>"+price+"</div></td>");
html.push("</tr>");
$('table.viewTable').append(html.join(''));
return price;}
I used the map function from Jade's answer to this question: Map in JavaScript.
My problem is either the displaying of the results or the procedure itself isn't correct. It should be inserting price rows first and then the totalPrice row afterwards; instead, the order is reversed, with totalPrice appearing first followed by the price rows. When I inserted an alert statement before insertion of totalPrice, it worked fine. Any suggestions? What's wrong with my code? Is jQuery compiled asynchronously?
Jep. Ajax calls are asynchronous, which means they don't execute immediately. You will need to keep track of the amount of completed ajax calls, and when all of them are done you can append the total.
Something like this:
var totalPrice = 0;
var completedAjaxCalls = 0;
map.each(function(key , value , i) {
params = {};
params.id = key;
// get datas from Controller class via ajax
ajax(url, params, false, function(result) {
totalPrice += setData(result , key , value);
completedAjaxCalls += 1;
if(completedAjaxCalls == map.length) {
$('table.viewTable tr:last').after("<tr class='title_bar'><td colspan='5' style='text-align: right;padding-right: 35px;'>"+num2Currency(totalPrice)+"</td></tr>");
}
});
});
Edit: there are probably better ways of achieving this, but since you still need to grasp the concept of asynchronous methods, I thought a simple approach was appropriate here.
You need to try
var totalPrice = 0;
var requests = [];
map.each(function(key, value, i) {
params = {};
params.id = key;
// get datas from Controller class via ajax
// make sure that `ajax()` return the promise returned by $.ajax()
requests.push(ajax(url, params, false, function(result) {
totalPrice += setData(result, key, value);
}));
});
$.when.apply($, requests).done(function() {
// alert("something!"); // this may satisfy my problem.. I have no idea..
// Total Price show at last row
$('table.viewTable tr:last')
.after("<tr class='title_bar'><td colspan='5' style='text-align: right;padding-right: 35px;'>"
+ num2Currency(totalPrice) + "</td></tr>");
})

Resources