Search code examples
sapui5

How can I bind a single property of my OData service to a Form?


Will you please tell me how to refer to the first tabular (and single) record? There is a table with only one record:

    <Table items="{WaybillsPlaces}" mode="SingleSelectMaster">
        <columns>
            <Column hAlign="Center">
                <header>
                    <Text text="Number" />
                </header>
            </Column>
        </columns>
        <items>
            <ColumnListItem>
                <cells>
                    <Text text="{CoNumber}" />
                </cells>
            </ColumnListItem>
        </items>
    </Table>

How can I read the field of the first record without a table?

    <Text text="{WaybillsPlaces[0]/>CoNumber}"/>

I get a table reply, but I do not want to display it in the table - I want to display it in the form in text boxes, so there will always be one line in the response.

    <entry>
    <id>
http://xxxxx.xxx.local:8000/sap/opu/odata/sap/LOGISTICS_SRV/WaybillsPlaces('4610103052')
    </id>
    <title type="text">WaybillsPlaces('4610103052')</title>
    <updated></updated>
    <content type="application/xml">
    <m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
    <d:CoNumber>46101030520001</d:CoNumber>
    </m:properties>
    </content>
    </entry>

EDIT (As @Denis description in the comments): I have an OData giving me the following entry

<entry>
    <id>
http://xxxxx.xxx.local:8000/sap/opu/odata/sap/LOGISTICS_SRV/WaybillsPlaces('4610103052')
    </id>
    <title type="text">WaybillsPlaces('4610103052')</title>
    <updated></updated>
    <content type="application/xml">
    <m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
    <d:CoNumber>46101030520001</d:CoNumber>
    </m:properties>
    </content>
    </entry>

How can I bind the CoNumber property with a Input within a From ??


Solution

  • give and ID to your table, get the table in your controller and call its 'getItems()' method. Then get the first object in the returned array:

    In your view

    <Table id="myTable" items="{WaybillsPlaces}" mode="SingleSelectMaster">
        <columns>
            <Column hAlign="Center">
                <header>
                    <Text text="Number" />
                </header>
            </Column>
        </columns>
        <items>
            <ColumnListItem>
                <cells>
                    <Text text="{CoNumber}" />
                </cells>
            </ColumnListItem>
        </items>
    </Table>
    

    In your controller

    onCertainEvent(evt){
      var oTable = this.getView().byId('myTable');
      var oFirstItem = oTable.getItems()[0]; // This is your ColumnListItem object in the first row
      var oFirstCellItem = oFirstItem.getCells()[0]; // This is your Text object in the first cell of the first row
      var sCellText = oFirstCellItem.getText(); // This is the text string in your first cell of the first row
    }
    

    EDIT: bind only the first item in your model

    In this case you can do aggregation binding. For aggregation binding you need multiplicity greater than 1. So do property binding in yout ColumnListItem with WaybillsPlaces/0/CoNumber

    <Table id="myTable" mode="SingleSelectMaster">
        <columns>
            <Column hAlign="Center">
                <header>
                    <Text text="Number" />
                </header>
            </Column>
        </columns>
        <items>
            <ColumnListItem>
                <cells>
                    <Text text="{WaybillsPlaces/0/CoNumber}" />
                </cells>
            </ColumnListItem>
        </items>
    </Table>
    

    EDIT: Data Binding options in certain events

    <!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_bluecrystal'
    			data-sap-ui-libs='sap.m'
    			data-sap-ui-xx-bindingSyntax='complex'></script>
    
    
    		<!-- DEFINE RE-USE COMPONENTS - NORMALLY DONE IN SEPARATE FILES -->
    
    		<!-- define a new (simple) View type as an XmlView
    		 - using data binding for the Button text
    		 - binding a controller method to the Button's "press" event
    		 - also mixing in some plain HTML
    		 note: typically this would be a standalone file -->
    
    		<script id="view1" type="sapui5/xmlview">
    		    <mvc:View
    				controllerName="my.own.controller"
    				xmlns:l="sap.ui.layout"
    				xmlns:core="sap.ui.core"
    				xmlns:mvc="sap.ui.core.mvc"
    				xmlns:f="sap.ui.layout.form"
    				xmlns="sap.m">
      				<Panel headerText="Table Panel">
        				<Table id="myTable" items="{/WaybillsPlaces}" mode="SingleSelectMaster" select="onRowPressed" updateFinished="onUpdateFinished">
                  <columns>
                      <Column hAlign="Center">
                          <header>
                              <Text text="Number" />
                          </header>
                      </Column>
                  </columns>
                  <items>
                      <ColumnListItem>
                          <cells>
                              <Text text="{CoNumber}" />
                          </cells>
                      </ColumnListItem>
                  </items>
              </Table>
            </Panel>
            <Panel id="Panel1" headerText="onAfterRendering Data Binding">
              <Label text="First Item - Property binding:"></Label>
              <Input id="Input1"></Input>
              <Label text="First Item - Element binding:"></Label>
              <Input value="{CoNumber}"></Input>
            </Panel>
            <Panel id="Panel2" headerText="onUpdateFinished Data Binding">
              <Label text="First Item - Property binding:"></Label>
              <Input id="Input2"></Input>
              <Label text="First Item - Element binding:"></Label>
              <Input value="{CoNumber}"></Input>
            </Panel>
            <Panel id="Panel3" headerText="onRowPressed Data Binding">
              <Label text="Selected Item - Property binding:"></Label>
              <Input id="Input3"></Input>
              <Label text="Selected Item - Element binding:"></Label>
              <Input value="{CoNumber}"></Input>
            </Panel>
    			</mvc:View>
    	</script>
    
    
    		<script>
    			// define a new (simple) Controller type
    			sap.ui.controller("my.own.controller", {
    				onAfterRendering: function(){
    				  var oTable = this.getView().byId('myTable');
              var oFirstItem = oTable.getItems()[0]; // This is your ColumnListItem object in the first row
              var oFirstCellItem = oFirstItem.getCells()[0]; // This is your Text object in the first cell of the first row
              
              var sFirstItemDataPath = oFirstCellItem.getBindingContext().getPath();
              this.getView().byId("Input1").bindProperty("value", sFirstItemDataPath + "/CoNumber");
              this.getView().byId("Panel1").bindElement(sFirstItemDataPath);
    				},
    				
    				onUpdateFinished: function(oEvent){
    				  var oTable = oEvent.getSource();
              var oFirstItem = oTable.getItems()[0]; // This is your ColumnListItem object in the first row
              var oFirstCellItem = oFirstItem.getCells()[0]; // This is your Text object in the first cell of the first row
              
              var sFirstItemDataPath = oFirstCellItem.getBindingContext().getPath();
              this.getView().byId("Input2").bindProperty("value", sFirstItemDataPath + "/CoNumber");
              this.getView().byId("Panel2").bindElement(sFirstItemDataPath);
    				},
    				
    				onRowPressed: function(oEvent){
              var oFirstItem = oEvent.getParameter("listItem"); // This is the pressed ColumnListItem object
              var oFirstCellItem = oFirstItem.getCells()[0]; // This is your Text object in the first cell of the pressed row
              
              var sFirstItemDataPath = oFirstCellItem.getBindingContext().getPath();
              this.getView().byId("Input3").bindProperty("value", sFirstItemDataPath + "/CoNumber");
              this.getView().byId("Panel3").bindElement(sFirstItemDataPath);
    				}
    			});
    
    			// instantiate the View
    			var myView = sap.ui.xmlview({viewContent:jQuery('#view1').html()}); // accessing the HTML inside the script tag above
    
    			// create some dummy JSON data
    			var data = {
    				  WaybillsPlaces: [{
      				  CoNumber: "Item 1",
      				},{
      				  CoNumber: "Item 2",
      				},{
      				  CoNumber: "Item 3",
      				}]
    				};
    			
    			// create a Model and assign it to the View
    			var oModel = new sap.ui.model.json.JSONModel();
    			oModel.setData(data);
    			myView.setModel(oModel);
    			
    			
    			// put the View onto the screen
    			myView.placeAt('content');
    
    		</script>
    	
    	</head>
    	<body id='content' class='sapUiBody'>
    	</body>
    </html>

    EDIT2: Bind a form input to a certain property in a OData Model

    Here I'm gonna use Northwind OData service, for ease of use, but you just need to use your own model. I used the "Customers" entitySet (a.k.a "Customers" DB table), and the "CustomerName" property in this entitySet.

    In your case (as per the given OData in the description, you should use the 'WaybillsPlaces' entity and your 'CoNumber' property. If you want to access one specific entry, provide the Key between parenthesis in the binding URL (in your case: WaybillsPlaces('4610103052')).

    I highly recommend you to read more about OData binding in UI5 (here and here). In a productive application, please set your OData model in the manifest.json file, to be sure that the $metadata call is done when the application starts, avoiding this way performance and many other issues.

    HERE THE SNIPPET