Search code examples
sapui5

How to add control to items statically


Sometimes in an aggregation binding, I need to add some controls to the generated list of items statically. Is there some elegant solution for this?

Let's say I have a Select with the following code:

<Select width="100%"
  items="{project>/Milestones}"
  selectedKey="0"
>
  <core:Item
    key="{project>Id}"
    text="{project>Name}"
  />
</Select>

Bound to a model with these data:

{
  Milestones: [
    {
      "Id": 1,
      "Name": "Cost Estimation 1",
      "Description": "Initial cost estimation"
    },
    {
      "Id": 2,
      "Name": "Pid Packages",
      "Description": "Ready for RFQs"
    },
    ...
  ]
}

I want to add an item to the Select with key="0" and value="< Blank >" and have that stay there even when the content of project>/Milestones is changed, but I don't want to add it to the actual aggregation.

The solutions that I have at the moment seem really hackish and create problems later on: creating a new model (property) leads to having the data duplicated in multiple lists and therefor it will probably get out of sync at some point. I've also tried adding the static items through binding events, but this is somewhat error prone and very verbose.


Solution

  • Ok here the promised snippet. First of all, if you just want to add a "blank" item, I recommend you to use ComboBox instead of Select, because you can always delete your selection. I added it to the snippet as well. But if you want to add an item, you just need to use the addItem() function described here

    I also added a button to modify your model, so you can see how the '< Blank >' item remains there even when you change it.

    Snippet

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta http-equiv='X-UA-Compatible' content='IE=edge'>
      <meta charset="utf-8">
    
      <title>MVC with XmlView</title>
    
      <!-- Load UI5, select "blue crystal" theme and the "sap.m" control library -->
      <script id='sap-ui-bootstrap' src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js' data-sap-ui-theme='sap_belize_plus' data-sap-ui-libs='sap.m' data-sap-ui-xx-bindingSyntax='complex'></script>
    
    
      <!-- DEFINE RE-USE COMPONENTS - NORMALLY DONE IN SEPARATE FILES -->
    
      <script id="view1" type="sapui5/xmlview">
        <mvc:View xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" controllerName="my.own.controller">
          <Title text="With Select" class="sapUiMediumMarginTop"></Title>
          <Select id="mySelect" width="100%" items="{ path: 'project>/Milestones', events:{ change: '.onSelectBindingChange' }, templateShareable: false}" selectedKey="0">
            <core:Item key="{project>Id}" text="{project>Name}" />
          </Select>
          <Title text="With ComboBox" class="sapUiMediumMarginTop"></Title>
          <ComboBox width="100%" items="{ path: 'project>/Milestones', templateShareable: false}" selectedKey="0">
            <core:Item key="{project>Id}" text="{project>Name}" />
          </ComboBox>
          <Button text="Modify Model" press="onButtonPressed" class="sapUiLargeMarginTop sapUiLargeMarginBottom"></Button>
        </mvc:View>
      </script>
    
    
      <script>
        // define a new (simple) Controller type
        sap.ui.controller("my.own.controller", {
          onSelectBindingChange: function(oEvent) {
            var oNewItem = new sap.ui.core.Item({
              key: 0,
              text: "< Blank >"
            });
            this.getView().byId("mySelect").addItem(oNewItem);
          },
    
          onButtonPressed: function(oEvent) {
            var aMilestones = this.getView().getModel("project").getProperty("/Milestones");
            aMilestones.push({
              Id: 4,
              Name: "New Milestone",
              Description: "Just a model modification"
            });
            this.getView().getModel("project").setProperty("/Milestones", aMilestones);
          }
        });
    
    
    
        /*** THIS IS THE "APPLICATION" CODE ***/
        // create some dummy JSON data
        var data = {
          Milestones: [{
              "Id": 1,
              "Name": "Cost Estimation 1",
              "Description": "Initial cost estimation",
            },
            {
              "Id": 2,
              "Name": "Pid Packages",
              "Description": "Ready for RFQs",
            },
            {
              "Id": 3,
              "Name": "Certificate Check",
              "Description": null,
            }
          ]
        };
        var oJSONModel = new sap.ui.model.json.JSONModel();
        oJSONModel.setData(data);
    
        // instantiate the View
        var myView = sap.ui.xmlview({
          viewContent: jQuery('#view1').html()
        }); // accessing the HTML inside the script tag above
        myView.setModel(oJSONModel, "project");
        // put the View onto the screen
        myView.placeAt('content');
      </script>
    
    </head>
    
    <body id='content' class='sapUiBody'>
    </body>
    
    </html>