Technical Articles
SAPUI5 : How to create form with OData (deep insert)
Purpose
The main goal of this blog is to show how to create a form based on OData service with two different entities. A general case would be a form with global informat such as personal data and address data. How to combine those two kind of data with low code.
Prerequisite
I’will suppose that you have a well level of UI5 development and you know well OData modeling. I will be theoritic with some concret example.
Context
Let’s say we have an OData service V2 generated by the SEGW transaction, in ABAP On-Premise environement. This service has two entities : PersonalDataSet and AddressSet. An association between those to entities with a relation 1 to n. We will create an application UI5 based on this service.
The application will have an simple form which will be mapped to the service like this:
Context UI5
The submit button will generate the data structure to create an entry into the backend.
The UI5 application
To achieve this, you do not need another JSON model, you only need the OData model.
First, to make the model available for data typing, you have to set it as a two way binding in the manifest.json.
"sap.ui5": {
(...)
"models": {
"": {
"dataSource": "mainService",
"preload": true,
"settings": {"defaultBindingMode": "TwoWay"}
}
}
}
Then you have to create new context binding for each entity.
onInit: function() {
this.getOwnerComponent().getModel().metadataLoaded().then((event) => {
// Create a new entry in the OData model
let oContextPersonal = this.getOwnerComponent().getModel().createEntry("/PersonalDataSet");
// Bind the new entry to the form Personal
this.getView().byId("idFormPersonal").bindElement(oContextPersonal.getPath());
this._tContextElement.push(oContextPersonal);
// Create a new entry in the OData model
let oContextAddress = this.getOwnerComponent().getModel().createEntry("/AddressSet");
// Bind the new entry to the form Address
this.getView().byId("idFormAddress").bindElement(oContextAddress.getPath());
this._tContextElement.push(oContextAddress);
});
},
Behind theย submitButton you have to create the deep structure before send it to the backend.
onSubmitData: function() {
var oData = {
d: this._tContextElement[0].getObject()
};
oData.d.toAddress = {
results: [this._tContextElement[1].getObject()]
};
// Clean up the oData from __metadata attribute
delete oData.d.__metadata;
delete oData.d.toAddress.results[0].__metadata;
// Call backend
this.getView().getModel().create("/PersonalDataSet", oData);
}
In that manner, you can use the OData model easily. Keep in mind the deep insert structure :
{ "d" : { principal EntityType "associationName" : { child EntityType }, "associationName" : { "results" : [ { child EntityType }, { child EntityType } ] } } }
Here is the exemple after submitting.
Conclusion
In some case, it is easier to use only one OData model to simplify your application. As I have show, few code permit to do a deep insertion.
Thank you but do we really need deep inserts ? Just wondering why not trying convert entire content to JSON and send in a string field to backend and deserialise in ABAP. Won't it be easy to handle nested structures ?
Long time i was planning to write article regarding to this but wondering how practical deep insert approach.
ย
Hello Bilen Cekic ,
Thank for your comment. Deep insert could be interesting when you need creation sequence. For instance, you will need to create Partners before creating new order. In that scenario, your UI form will retreive all the data you need, and then send to the backend in once. Thus, the backend will create first the Partner, and secondly the order with the newly created partner.
Why not using another JSON model for that? Well, I would say why using a JSON model whereas the OData model do the job? With a second model, you will have to do a mapping between both model anyway. It is a double job.
regards, Joseph
thank you but still entire ODATA config on SEGW, preparation of classes to do this still a lot of work. I can understand if you are trying to publish in a company which has integration with their ODATA architecture (if any ) to follow the book, but i still found totally unnecessary..
JSON model is simple, you can fill inside what you want , you can have a nested structure there. Once you send to ABAP, you have all flags, arrays, structures. It is flexible, you don't need to visit SEGW again if you need another 1 more layer on your JSON model or any other columns.
I understand your concern, but it is complicating the process.(my personal opinion).
Thanks anyway
I love debating and having other opinions than me. it's cool ๐ thanks
In the idea, if you have built your OData model well upstream, you shouldn't need any more complex structures to do in JSON. But I will admit that using the OData model can in some cases be very complicated to set up, whereas classical JSON modeling is much more flexible.
In my projects (and not just in books), I try to use OData modeling as much as possible. And I manage to do it very frequently.
With pleasure.
thanks, Joseph.
We are totally on opposite site. I do as less as possible actually never :). I created ODATA service 4 years ago in our company which has flexible columns and used i think for 8 big projects with nearly 100+ BADI implementations supporting it. Still actively using same architecture. I think we never visit SEGW tcode again after creationg it.
Any ABAPer even JR or SR, does not need to know ODATA modelling. As long as you are good at internal table processing and architecture, it is what i need in my project team.
It is something like below;
Unfortunately, when we deviate from the standard, I can only disagree. ๐
How do you manage the Fiori Elements? How do you manage the acquisition of OData skills in your team? S4Hana is OData oriented, so the architecture you have implemented is too specific. How will you migrate your teams to S4? What about the Cloud programing architectre?
Moreover, how do you manage the Analytical List page? If you follow the Fiori best practices, OData is a real "quick win".
With please,
Joseph
On my side, I am wondering how you handle the entries that have been started to be created on the backend, but not updated with the save button from the frontend? To avoid to pollute the backend with started and not finalized data
Hi Denis Galand ,
I don't get you much ๐ sorry. In my case, if you are on the creation of a partner and address, then the data are all send in once. The backend will create first the address and secondly the partner, and then link the both entities. I have not pending data in that xase.
Hope I have answer to your question.
Regards,
Joseph
I agree with the approach presented. by the way I recommend abapers to consider diving into "ABAP RESTful Application Programming Model (RAP)"