Hello All,

Many times I personally / my colleagues have encountered this scenario, where a XML Model need to be used throughout the application and not sure how to use it. To avoid this, most of us try to convert the data into JSON, since it is bit easy compared to XML.

However in this blog, I try to explain how we can use XML Models in UI5 which is more required for SAP MII related services where the data response is in XML format.

Models:

A model in the MVC paradigm holds the data and provide methods like Create, Read, Update and Delete.

We have totally four types of models in SAPUI5:

     – JSON Model

     – XML Model

     – OData Model

     – Resource Model

For more information, please check this link: Models – UI Development

JSON and XML models are client-side models and OData model is a server side model. We have lots of examples with JSON and OData model. But, I didn’t found much for XML model which serves the purpose.

SAP MII provides most of the data response in standard XML format.

We have a Runner service which provides the output in XML format. To avoid XML, generally most of us wrap the transaction into a query object to fetch the response in JSON.

I would suggest that, instead of creating a new Query object, let us make use of XML structure itself.

Let us go through different operations like Create / Read / Update / Delete and Save using XML model.

Read:


I have following XML Data:


<Rowsets CachedTime="" DateCreated="2016-07-03T04:08:56" EndDate="2016-07-03T04:08:56" StartDate="2016-07-03T03:08:56">
    <Rowset>
        <Columns>
            <Column Description="ProductId" MaxRange="1" MinRange="0" Name="ProductId" SourceColumn="ProductId" />
            <Column Description="Name" MaxRange="1" MinRange="0" Name="Name" SourceColumn="Name" />
            <Column Description="Category" MaxRange="1" MinRange="0" Name="Category" SourceColumn="Category" />
            <Column Description="SupplierName" MaxRange="1" MinRange="0" Name="SupplierName" SourceColumn="SupplierName" />
            <Column Description="WeightMeasure" MaxRange="1" MinRange="0" Name="WeightMeasure" SourceColumn="WeightMeasure" />
        </Columns>
        <Row>
            <ProductId>1239102</ProductId>
            <Name>Power Projector</Name>
            <Category>Projector</Category>
            <SupplierName>Titanium</SupplierName>
            <WeightMeasure>1467</WeightMeasure>
        </Row>
        <Row>
            <ProductId>2212-121-828</ProductId>
            <Name>Gladiator MX</Name>
            <Category>Graphics Card</Category>
            <SupplierName>Technocom</SupplierName>
            <WeightMeasure>321</WeightMeasure>
        </Row>
        <Row>
            <ProductId>K47322.1</ProductId>
            <Name>Hurricane GX</Name>
            <Category>Graphics Card</Category>
            <SupplierName>Red Point Stores</SupplierName>
            <WeightMeasure>588</WeightMeasure>
        </Row>
        <Row>
            <ProductId>22134T</ProductId>
            <Name>Webcam</Name>
            <Category>Accessory</Category>
            <SupplierName>Technocom</SupplierName>
            <WeightMeasure>700</WeightMeasure>
        </Row>
    </Rowset>
</Rowsets>


Now, I need to bind above XML data to the table.

In controller onInit, it would be:


        onInit: function(oEvent) {
          var oModel = new XMLModel();
          oModel.loadData("data.xml");
          oModel.attachRequestCompleted(function(oEvent) {
            sap.ui.getCore().setModel(oEvent.getSource());
          });
        }


Since, I am loading the file locally I have to use the above code. But in your case, there would be an AJAX call to Query Template / Transaction etc, and then in the success condition you can set the data to model.

Now table XML code would be:


<Table id="idProductsTable"
          mode="SingleSelectMaster"
          selectionChange="onSelectionChange"
          items="{/Rowset/0/Row}"
          class="TableStyle">
    <headerToolbar>
        <Toolbar>
            <ToolbarSpacer />
            <Button text="Insert Item" type="Emphasized" press="onInsert" />
            <Button text="Edit Item" type="Emphasized" press="onEdit" />
            <Button text="Save Item" type="Emphasized" press="onSave" />
            <Button text="Delete Item" type="Reject" press="onDelete" />
        </Toolbar>
    </headerToolbar>
    <columns>
        <Column>
            <Label text="ID" />
        </Column>
        <Column>
            <Label text="Product" />
        </Column>
        <Column>
            <Label text="Category" />
        </Column>
        <Column>
            <Label text="WeightMeasure" />
        </Column>
    </columns>
    <items>
        <ColumnListItem>
            <cells>
                <Input value="{ProductId}" editable="false" class="InputStyle" />
                <Input value="{Name}" editable="false" class="InputStyle" />
                <Input value="{Category}" editable="false" class="InputStyle" />
                <Input value="{WeightMeasure}" editable="false" class="InputStyle" />
            </cells>
        </ColumnListItem>
    </items>
</Table>


If you see the table items binding path, it is bound to: “{/Rowset/0/Row}”, if you’re not sure about the same, you can debug to make it clear:

/wp-content/uploads/2016/08/2016_08_09_19_27_36_1011778.jpg


Once data is bound to table, the same would be displayed in ‘items’ aggregation of table.


Create:


Since the Item template is already created, we just need to push an empty ‘Row’ node with sub nodes to XML structure. In result it creates a new Column List Item in table.



        onInsert: function(oEvent) {
          //Create
          var oModel = sap.ui.getCore().getModel();
          var oModelData = oModel.getData();
          var oRow = $(oModelData).find('Row')[0];
          var oNewChildNode = oModelData.createElement("Row");
          var oNodes = oRow.children;
          for (var i = 0; i < oNodes.length; i++) {
            var oNodeName = oNodes[i].nodeName;
            var xmlNode = oModelData.createElement(oNodeName);
            xmlNode.appendChild(document.createTextNode(""));
            oNewChildNode.appendChild(xmlNode);
          }
          var oRowset = $(oModelData).find('Rowset')[0];
          oRowset.appendChild(oNewChildNode);
          oModel.setData(oModelData);
          var oTable = oEvent.getSource().getParent().getParent();
          jQuery.sap.delayedCall(100, null, function() {
            var oLength = $(oModelData).find('Row').length;
            var oItem = oTable.getItems()[oLength - 1];
            var oCells = oItem.getCells();
            for (var j = 0; j < oCells.length; j++) {
              oCells[j].setEditable(true);
            }
          });
        }


Update:

We just need to make the item fields ‘editable’ property to true and once the save item button is pressed the fields will be non-editable and data will be saved in XML Model.


        onEdit: function(oEvent) {
          //Update
          var oTable = oEvent.getSource().getParent().getParent();
          var oSelectedItem = oTable.getSelectedItem();
            var oCells = oSelectedItem.getCells();
            for (var j = 0; j < oCells.length; j++) {
              oCells[j].setEditable(true);
            }
        }


Delete:

Delete the selected Item data from table and remove the selected Row node from XML Model.


        onDelete: function(oEvent) {
          //Delete
          var oTable = oEvent.getSource().getParent().getParent();
          var oSelectedItem = oTable.getSelectedItem();
          if (oSelectedItem === null) {
            MessageBox.alert("Please select an Item to Delete", {
              icon: sap.m.MessageBox.Icon.ERROR,
              title: "Error"
            });
          } else {
            var that = this;
            MessageBox.confirm("Are you sure you want to delete selected item?", {
              icon: sap.m.MessageBox.Icon.WARNING,
              title: "Delete",
              actions: [sap.m.MessageBox.Action.YES, sap.m.MessageBox.Action.NO],
              onClose: function(oEvent) {
                that.fnCallbackConfirm(oEvent, oTable, oSelectedItem);
              }
            });
          }
        },
        fnCallbackConfirm: function(oEvent, oTable, oItem) {
          if (oEvent == "YES") {
            var oIndex = oTable.indexOfItem(oItem);
            var oModel = sap.ui.getCore().getModel();
            var oModelData = oModel.getData();
            var oRow = $(oModelData).find('Row')[oIndex];
            var oRowset = $(oModelData).find('Rowset')[0];
            oRowset.removeChild(oRow);
            oModel.setData(oModelData);
            oTable.removeSelections(true);
          } else {
            oTable.removeSelections(true);
            return false;
          }
        }


Save:

Once we have the new data in XML file / model, here we need to make an AJAX call to query template where we can pass this parameter as XML type to SQL Stored Procedure and loop through XML file to update / insert the records to SQL tables.

Full Demo: Since there is no connection with MII, I just made a sample using Plunker CRUD Application – XML Model


Working Snippet:

Capture.gif


Regards,

Sai.

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Gary King

    Great example Sai. I can see via the video you have embedded that the Insert functionality works, but when running the code via Plunker all functionality works, except the [Insert] function, and I wondered if you knew why this was?.

     

    (0) 

Leave a Reply