Skip to Content
Technical Articles
Author's profile photo Joseph BERTHE

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%20UI5

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.

 

Assigned Tags

      10 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Bilen Cekic
      Bilen Cekic

      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.

      Β 

      Author's profile photo Joseph BERTHE
      Joseph BERTHE
      Blog Post Author

      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

      Author's profile photo Bilen Cekic
      Bilen Cekic

      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

      Author's profile photo Joseph BERTHE
      Joseph BERTHE
      Blog Post Author

      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.

      Author's profile photo Bilen Cekic
      Bilen Cekic

      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;

      I will write an article regarding "Simplifying your OData design". Let me know your thoughts about it πŸ™‚

      Author's profile photo Joseph BERTHE
      Joseph BERTHE
      Blog Post Author

      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

      Author's profile photo Mourad CHERIFI
      Mourad CHERIFI

      Hi Bilen,

      Your solution is interesting but I think it's specific to your need. In the context I'm working in for example, which is implementing rich Fiori Elements and UI5 applications, it would be very hard and inefficient to work with JSON models. I do not use Deep Insert though, I prefer use change set processing in deferred mode when it comes to create or update several objects in a transactional way.
      There are so many features that are supported by the ODataModel that would be very difficult and time-consuming to re-implementΒ using JSON Models : detect and collect changes on the screen,Β message handling and display, concurrent access to resources, draft management ... IΒ not to mention the huge simplification of Javascript code on UI5 applications or simply the implementation of FIORI Elements which would be just impossible using your approach.Β 

      But I totally agree that the simplest solution to your problem is often the best one πŸ˜‰

      Regards

      Author's profile photo Denis Galand
      Denis Galand

      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

      Author's profile photo Joseph BERTHE
      Joseph BERTHE
      Blog Post Author

      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

      Author's profile photo Tomas Ngoma
      Tomas Ngoma

      I agree with the approach presented. by the way I recommend abapers to consider diving into "ABAP RESTful Application Programming Model (RAP)"