attachRequestCompleted errors out in init() - sapui5

I am using following snippet which I am using in init function. My oAppModel is getting loaded with the data. However, oAppModel.attachRequestCompleted() does not get executed even. I have tried to pass oEvent also, but when I use oEvent, it says oEvent is not defined.
var oAppModel = new sap.ui.model.json.JSONModel();
oAppModel.loadData(oData);
//attach
oAppModel.attachRequestCompleted(function(){
//get value:
var soldto = oAppModel.getProperty("/SoldTo/0/Name");
});
Could you please help ?

you are loading data (oData) into the model hence not HTTP(s) request is made. therefore, requestCompleted event is not fired.
it will fire if you do this.
var oAppModel = new sap.ui.model.json.JSONModel();

Related

SAPUI5: getModel returns undefined if called within the same function of setModel

I'm trying to set a model and retrieving it from OData after pressing a certain button.
The problem is when I call getModel right after setting the model, it returns undefined.
However, if I call getModel from another function (after model being stetted from other functions), it returns the desired output.
Code for reference:
onPressButton1: function(){
var vEntityURL = "/CustomerSet(ID='000')";
var sServiceUrl = "/Customers_SRV/";
var oServiceModel = new sap.ui.model.odata.ODataModel(sServiceUrl, true);
var oJsonModel = new sap.ui.model.json.JSONModel();
oServiceModel.read(vEntityURL, {
success: function(oData) {
oJsonModel.setData(oData);
}
});
this.getView().setModel(oJsonModel, "Customers");
var oCustomer = this.getView().getModel("Customers");
console.log(oCustomer.getProperty("/Name"));
}
The above returns undefined in the console.
However, it works if I press another button with the following function.
onPressButton2: function(){
var oCustomer = this.getView().getModel("Customers");
console.log(oCustomer.getProperty("/Name"));
}
This is not a sapui5 problem, it is the common behaviour of asynchronous code: you can be sure to have your data only in the success callback of the read method.
Move the last three lines of code inside the success function and you're done :-)

SAPUI5 change operationMode to client in runtime

I am using SmartTable in my project.
I need to request some data from backend at begin and then work on received data in frontend.
By data, that i need from backend i must send some filter.
So i need at begin the operationMode Server, and after data come change it to Client
My SmartTable xml
<smartTable:SmartTable id="ReportSmartTable" entitySet="OwnSet"
tableBindingPath="/OwnSet" tableType="AnalyticalTable"
beforeRebindTable="onBeforeRebindTable" >
onBeforeRebindTable
onBeforeRebindTable: function (oEvent) {
console.log("onBeforeRebindTable");
var oBindingParams = oEvent.getParameter("bindingParams");
oBindingParams.filters.push(new sap.ui.model.Filter("Prop", "EQ", "Value"));
},
in onInit i set listener, to change the operation mode after data receiving
var oTable = this.getView().byId("ReportSmartTable"); //Get Hold of the table control
oTable.attachDataReceived(function (oEvent) { //Hits when the data is received from back-end server
this.getModel().defaultOperationMode = "Client"; //Set operation mode to Client
var oSource = oEvent.getSource();
oSource.bClientOperation = true; //Set Client Operation to true
oSource.sOperationMode = "Client"; //Set operation mode to Client
}.bind(this));
i have also tried to change operationMode by following
this.getOwnerComponent().getModel().sDefaultOperationMode = "Client";
this.getOwnerComponent().getModel().defaultOperationMode = "Client";
this.getModel().sDefaultOperationMode = "Client"; //Set operation mode to Client
this.getModel().defaultOperationMode = "Client"; //Set operation mode to Client
but it doesn't work.
If i make some filter after data is received, there still comes request to backend.
By making Client operationMode from begin, onBeforeRebindTable is called before request, but the filter is not sended with batch
You can't update the operation mode after a model is created. Even if you update the private attribute sDefaultOperationMode, it will not affect existing bindings.
You can specify the operationMode per binding, for example in a list:
<List items="{path:'/myset',parameters:{operationMode:'Client'}}" ...>
and use ListBase.bindItems to re-create a binding with a different operation mode.
For a SmartTable, however, you'd have to modify the internal table bindings and this would probably break a lot of things, therefore it's discouraged. Maybe the Smart Table is not the best fit for your use case.

What is the difference between setJSON, setData and loadData?

This is regarding the mentioned methods of sap.ui.model.json.JSONModel in SAPUI5:
setJSON
setData
loadData
What is the difference between these 3 methods? When do we use these methods and can we use more than 1 of them for the same purpose?
Have a look at the well documented API Reference for JSONModel.
In summary (from SAP Documentation):
setData: Sets the data, passed as a JS object tree, to the model.
e.g
var data = {
"ProductCollection": [{
"titleId": 0,
"Name": "Olayinka O",
"ProductId": "001",
"chartValue": 75,
"ProductPicUrl": "sap-icon://competitor"
}]
};
var oModel = new sap.ui.model.json.JSONModel(data);
//OR
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
/*setdata, could also be a odata url in json format*/
loadData:
Load JSON-encoded data from the server using a GET HTTP request and store the resulting JSON data in the model. Note: Due to browser security restrictions, most "Ajax" requests are subject to the same origin policy, the request can not successfully retrieve data from a different domain, subdomain, or protocol.
e.g. you can use this to load/GET changes to the data/model and automatically updates the view if that specific model has being binded by reloading the url. If you use load, you don't need the other two in my opinion and loadData with not work on local json data.
var sURL = "https://cors-anywhere.herokuapp.com/https://services.odata.org/V3/Northwind/Northwind.svc/Products?$format=json";
var oModel = new sap.ui.model.json.JSONModel();
//if called in setInterval, all changes in the backend will be updated in the view if binded in this case every second
setInterval(oModel.loadData(sURL, true), 1000);
setJSON :
Sets the data, passed as a string in JSON format, to the model.
i.e. Same as Set Data but strict JSON
Luckily, the source code of UI5 is quite readable and often the better documentation than most of the API descriptions. Here is what each one of the APIs does basically:
setJSON
"Parse the JSON text and call setData"
JSONModel.prototype.setJSON = function(sJSON, bMerge) {
var oJSONData;
try {
oJSONData = jQuery.parseJSON(sJSON);
this.setData(oJSONData, bMerge);
} catch (e) {
// ...
}
};
Source
setData
"Store the data and notify all dependent bindings (checkUpdate)"
JSONModel.prototype.setData = function(oData/*plain JS object*/, bMerge){
if (bMerge) {
this.oData = /* merge with existing data */;
} else {
this.oData = oData;
} // ...
this.checkUpdate(); // notifies dependent bindings
};
Source
loadData
"Load data from the given remote URL and call setData" --> Please check the source here.
In short, they all call setData at some point.
Which API to call in which situation depends on in which format you have the data available.
The data are in JSON text --> setJSON
The data are somewhere else --> loadData
I already have the data in JS object / array ---> setData
setData
You have a JavaScript object and want to use this data as your model
const oJSONData = {
data: {
id: 4,
first_name: "Eve",
last_name: "Holt",
avatar: "https://s3.amazonaws.com/uifaces/faces/twitter/marcoramires/128.jpg"
}
};
oJSONModel.setData(oData);
setJSON
You have a String that when parsed represents a JavaScript object and want to use this data as your model
const sJSONData = '{"data":{"id":4,"first_name":"Eve","last_name":"Holt","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/marcoramires/128.jpg"}}';
oJSONModel.setJSON(sJSONData);
loadData
You want to access a remote API which returns data as JSON and want to use this data as your model
const sURL = "https://reqres.in/api/users/4";
oJSONModel.loadData(sURL);

JSONModel: How to merge with existing data when calling "loadData"

I have the following coding in my SAP UI5 application Controller:
var myView = this.getView();
var data1 = { "myDate": new Date() };
oModel.loadData("products.json");
oModel.setData(data1);
myView.setModel(oModel);
Where products.json - just a simple data for the table on the screen.
And I can see only products.json data on the screen as a result, and myDate with empty value inside oModel (checked in debug).
In case I comment loadData string, myDate value is on the screen and looks good.
How I can use them together? What is the best practice for such cases?
The model's loadData is an asynchronous process, so it will update the model after you have set it synchronously with data1.
Also, setData() will wipe everything already in the model, so better use setProperty and update only a specific node in your model.
You should add the static data once you have loaded it from file:
oModel.attachRequestCompleted(function() {
oModel.setProperty("/myExtraData", data1);
});
Your added date is then available via /myExtraData/myData
Merge new data with existing one with bMerge parameter of setData().
oModel.loadData("products.json");
var data1 = {
"myDate": new Date()
};
oModel.attachRequestCompleted(function() {
oModel.setData(data1, true);
});
The API loadData has also a bMerge option.
oModel.setData({ myDate: new Date() });
oModel.loadData("products.json", null, true, "GET", /*bMerge*/true);
// Merged results:
{
myDate: /*date object*/,
produces: [/*...*/]
}
No need to register an event handler for requestCompleted.

custom webapi function binding to store extjs grid

I need help to bind data returned by a custom webapi function. Say my webapi function calling syntax is like below:
var filter = {<some conditions here>};
Myapp.systemcontroller.Getdata(filter).then(function(result){
--- this result contain my data and total record
});
How can I bind this function to the store proxy and then bind it to a grid?
Any help would be greatly appreciated.
You can use different way to add the data to store. Its depend on your data structure(array or object).
grid.getStore.add(model) -ref:
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.data.Store
grid.getStore.loadData(data,[append]) - ref:
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.data.Store-method-loadData
grid.getStore.loadRawData(data,[append]) - ref:
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.data.Store-method-loadRawData
grid.getStore.loadRecords(records,options) - ref:
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.data.Store-method-loadRecords
In your case, you can use loadRecords() or add()
The problem has been fixed. I m not using any proxy in my store.. I m using the above api to retrieve the data and bind it to store using loadData method. Then I will set the totalProperty of my toolbar as well
-- on load
Myapp.systemcontroller.Getdata(f).then(function (data) {
gridstore.loadData(data.Items);
gridstore.totalCount = data.TotalNumber;
var pgTb = Ext.getCmp('DataListPgTb');
pgTb.onLoad();
me.getLogList().setLoading(false);
});
Then in the toolbarchange event
toolBarChange: function (tbar, pageData, eOpts) {
var pageSize = PrIns.getApplication().Configuration.PageSize;
var me = this;
me.getLogList().setLoading(true);
var f = Ext.create(MyApp.webapi.filter.LogFilter', { pageIndex: pageData, pageSize: pageSize, orderBy: 'Ascending' });
var gridstore = this.getLogList().getStore();
Myapp.systemcontroller.Getdata(f).then(function (data) {
gridstore.loadData(data.Items);
gridstore.totalCount = data.TotalNumber;
gridstore.currentPage = pageData;
var pgTb = Ext.getCmp('DataListPgTb');
pgTb.onLoad();
me.getLogList().setLoading(false);
});
return false;
},
return false will prevent us from calling the proxy