In this blog lets take a look at implementing CRUD operations on OData V4 Model. There are various techniques to read and write data from a service and the most widely used method is as shown in the documentation: https://sapui5.hana.ondemand.com/#/topic/6c47b2b39db9404582994070ec3d57a2%23loioff667e12b8714f3595e68f3e7c0e7a14
But this might not be the same case when we are trying to read or write data from Odata V4 model. One simple way is to use ajax requests but having multiple ajax requests in a UI5 application might not be ideal. This blog will help you give insight on performing CRUD operations on a V4 model from the controller.
This blog is inspired from the official documentation – https://sapui5.hana.ondemand.com/#/topic/bcdbde6911bd4fc68fd435cf8e306ed0
CREATE:
The following snippet shows how to create a new row in an entity. You can send in the primary key which usually would be an ID as well as one of the parameters, if its an UUID then the ID will be generated on create action. In the following example I am adding a new book into the ‘Books’ entity.
let oModel = this.getView().getModel();
let oBindList = oModel.bindList("/Books");
oBindList.create({
title: "Test Book",
stock: 100,
description: "Test Description"
});
READ:
To read an entity here is an example:
handleRead: function(oEvent){
let oModel = this.getView().getModel();
let oBindList = oModel.bindList("/Books");
oBindList.requestContexts().then(function (aContexts) {
aContexts.forEach(oContext => {
console.log(oContext.getObject());
});
});
}
This is by far the simplest way to read the data. Here it uses requestContexts() to get the context and each context can be further extracted by using getObject() which displays all the columns in each row.
This read method can also be further improvised for reading associations and compositions. For example, if each book is associated with an Author, where Author is a different entity with author’s details then all the details can be read by using expand as shown below:
handleRead: function(oEvent){
let oModel = this.getView().getModel();
let bookID = oEvent.getSource().getBindingContext().getObject().ID;
let aFilter = new sap.ui.model.Filter("ID", sap.ui.model.FilterOperator.EQ, bookID);
oModel.bindList("/Books", undefined, undefined, aFilter, {
$expand: "author($expand=book)"
}).requestContexts().then(function (aContexts) {
aContexts.forEach(oContext => {
console.log(oContext.getObject());
});
});
}
you can read multiple associations/compositions in a single batch request as above, the ($expand=book) is ofcourse optional, it helps to dig more deeper into the associations, and can also apply filter before reading. You can have an array of filters as well.
UPDATE:
To update, again its is a very simple way, just like the setProperty() in Odata V2
handleEdit: function(oEvent){
let oModel = this.getView().getModel();
let bookID = oEvent.getSource().getBindingContext().getObject().ID;
let oBindList = oModel.bindList("/Books");
let aFilter = new sap.ui.model.Filter("ID", sap.ui.model.FilterOperator.EQ, bookID);
oBindList.filter(aFilter).requestContexts().then(function (aContexts) {
aContexts[0].setProperty("description", "new description");
aContexts[0].setProperty("title", "Test");
});
},
Here you can set as many properties as required, here I have not used promise, but you can also add all the requests in a promise and execute them together in a single batch request. This way it helps you control the execution order as well.
DELETE:
Delete operation is very similar to create.
handleDelete: function(oEvent){
let oModel = this.getView().getModel();
let bookID = oEvent.getParameters().listItem.getBindingContext().getObject().ID;
let oBindList = oModel.bindList("/Books");
let aFilter = new sap.ui.model.Filter("ID", sap.ui.model.FilterOperator.EQ, bookID);
oBindList.filter(aFilter).requestContexts().then(function (aContexts) {
aContexts[0].delete();
});
},
Here after the filter I am expecting only one row so I am directly initiating the delete, you can also use a loop or index function to delete multiple rows.
To get more insight you can also checkout the repo:
The above operations are performed with listBinding, you can also do it with contextBinding. If there exists a set or a view which expects an input, it can be done as following:
let oContextBinding = oModel.bindContext("/SomeEntity(ID='" + entityID + "')/set");
oContextBinding.requestObject().then(function (aContexts) {
console.log(aContexts);
}.bind(this), function (oError) {
console.log(oError);
});
The syntax for these operations are referred from https://sapui5.hana.ondemand.com/#/api/sap.ui.model.odata.v4.Context
On completion of the above operations successfully, it can also be caught with these functions https://sapui5.hana.ondemand.com/#/api/sap.ui.model.odata.v4.ODataListBinding for performing further actions.
Thank you for reading! I hope this was helpful.