CD267 Exercise

19
DEVELOPING APPLICATIONS WITH HTML5 TOOLKIT AND SAP NETWEAVER GATEWAY CD267 Exercises / Solutions Tim Back SAP AG Stefan Beck SAP AG Peter Müssig SAP AG

description

CD267 EXER

Transcript of CD267 Exercise

Page 1: CD267 Exercise

DEVELOPING APPLICATIONS WITH HTML5

TOOLKIT AND SAP NETWEAVER GATEWAY

CD267

Exercises / Solutions Tim Back SAP AG Stefan Beck SAP AG Peter Müssig SAP AG

Page 2: CD267 Exercise

2

Introduction

In this exercise you will learn to create a first Hello World Application using SAPUI5 Tools. As second step,

you will build a more complex application using Gateway OData Services and – if the time allows – you will

extend the SAPUI5 control set and use of the new control within your application from the previous exercise

step.

01_Create a “Hello World”-Application

To get familiar with the SAPUI5 tools as a first step we create an easy “HelloWorld” application that will be extended during the subsequent exercise steps.

010_Create a new SAPUI5 Application Project Create a new application project in Eclipse using the SAPUI5 application wizard and add a first UI Element:

Open the File-menu in Eclipse and select New… > Other… > SAPUI5 Application Development > Application Project

Name the project teched2012

Name the view “SalesOrderList” and use a JavaScript view (default)

Finish!

This creates a SAPUi5 application project. The project contains the following files:

WebContent/index.html (application page)

WebContent/teched2012/SalesOrderList.view.js (SalesOrderList View)

WebContent/teched2012/SalesOrderList.controller.js (SalesOrderList Controller)

Open the SalesOrderList.view.js and add a Button as content, e.g.: createContent : function(oController) { return new sap.ui.commons.Button({ text: "Hello World", press: function(oEvent) { alert(this.getText()); } }); }

011_Test the application locally

Run the application on the Jetty Server which is embedded in Eclipse to see a first local test of your SAPUI5 application:

Open the project context menu of your project (right click on your project in the Eclipse Project Explorer view) > Run as > Web App Preview > Finish

Now an embedded browser appears showing the application containing a Button which alerts “Hello World” once it is clicked.

Page 3: CD267 Exercise

3

012_Deploy the application on an ABAP server

The next step is to move the application into the ABAP server by using the SAPUI5 ABAP Repository team provider:

Share the project

Open the context menu of your project in the Eclipse Project Explorer (right click) > Team > Share…

Select “SAPUI5 ABAP Repository”

Browse for M11 system

Enter client “800” and enter your username and password

Create a new BSP application named “Z_TE12_<username>” (name is restricted to 12 characters – clarify the user ids for the participants!)

Use the name also as description

As package choose $TMP

Finish

Push the application into the SAPUI5 ABAP Repository

Project context menu > Team > Submit > Finish

013_Test the application on an ABAP server To test the application, you have to logon to the ABAP system, find the application in the repository and trigger the server test:

Logon to the ABAP system and perform a test

Open SAP Logon and enter the M11 system logon and open SE80 (/nse80)

Open the repository browser, select the Local Objects

Expand the $TMP object till you application and open the folder “Pages with Flow Logic” > “WebContent”

On the index.html use the context menu and trigger “Test”

Now you can see you SAPUI5 application deployed and running on an ABAP server

Page 4: CD267 Exercise

4

02_Create a “SalesOrderList”-Application

After having made first experience using the SAPUI5 Tools, we’ll create a richer application by implementing a Sales Order List displaying some details of a selected order. See below the application that is going to be built:

We use the following Gateway service which produces OData: http://wdflbmt0818.wdf.sap.corp:51080/sap/opu/odata/sap/ZCD204_EPM_DEMO_SRV/?$format=xml The metadata can be found here: http://wdflbmt0818.wdf.sap.corp:51080/sap/opu/odata/sap/ZCD204_EPM_DEMO_SRV/$metadata

020_Create a Sales Order List View Continue with the application from exercise 1:

First we add the sap.ui.table library to the list of the imported libraries in the bootstrap tag in the index.html page.

Open the SalesOrderList.view.js and we create a Table with the following columns: ID, Total Sum, Currency, Customer ID and Customer:

createContent : function(oController) {

// main orders table var oTable = new sap.ui.table.Table({ id: this.createId("orders_table"), selectionMode: sap.ui.table.SelectionMode.Single, rowHeight: 30,

Page 5: CD267 Exercise

5

columns: [ new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "ID" }), template: new sap.ui.commons.TextView({ text: "{SalesOrderID}" }) }), new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "Total Sum" }), template: new sap.ui.commons.TextView({ text: "{TotalSum}" }), sortProperty: "TotalSum" }), new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "Currency" }), template: new sap.ui.commons.TextView({ text: "{Currency}" }), sortProperty: "Currency" }), new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "Customer ID" }), template: new sap.ui.commons.TextView({ text: "{BusinessPartnerID}" }), sortProperty: "CustomerID" }), new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "Customer" }), template: new sap.ui.commons.TextView({ text: "{CustomerName}" }), sortProperty: "CustomerName" }) ] }); return oTable; }

021_Connect the table with the Gateway OData service The connection is done in the controller initialization.

Before we start to connect to the ODataModel we need some helper code which allows us to connect to a model across domain borders ( CORS! - https://sapui5.netweaver.ondemand.com/sdk/#docs/guide/TestingInEclipse.html )

getServiceUrl : function(sServiceUrl) {

// for local testing prefix with proxy: if (window.location.hostname == "localhost") { return "proxy/http/wdflbmt0818.wdf.sap.corp:51080" + sServiceUrl; } else { return sServiceUrl; }

},

Now in the onInit method create the ODataModel and set it on the Table. As last step bind the Table properly

against the SalesOrders collection: onInit: function() {

var sServiceUrl = this.getServiceUrl("/sap/opu/odata/sap/ZCD204_EPM_DEMO_SRV/");

Page 6: CD267 Exercise

6

var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl); this.getView().setModel(oModel); var oTable = this.byId("orders_table"); oTable.bindRows("/SalesOrders"); }

Refresh the application and you should see the Table displaying the Sales Orders.

022_Create a sales order detail form As next step, a new view is added to display details of the orders in the list:

Create a new view via project context menu > New… > Other… > SAPUI5 Application Project > View and name it SalesOrderDetails (the type is also JSON View) > Finish

In the createContent function of the view we create a Panel containing a MatrixLayout with the relevant form fields: ID, Created At, Total Sum, Currency and Note:

createContent : function(oController) {

// Panel containing order details var oPanel = new sap.ui.commons.Panel({ id: this.createId("order_detail_panel"), text: "Sales Order Details", width: "100%" }); // Layout for the order detail (a form) var oLayout = new sap.ui.commons.layout.MatrixLayout({ width: "100%", widths: [ "25%", "75%" ] }); // add form rows using helper function oLayout.createRow(new sap.ui.commons.Label({text: "ID"}), new sap.ui.commons.TextField({value: "{SalesOrderID}", width: "100%", editable: false})); oLayout.createRow(new sap.ui.commons.Label({text: "Created At"}), new sap.ui.commons.TextField({value: "{CreatedAt}", width: "100%", editable: false})); oLayout.createRow(new sap.ui.commons.Label({text: "Total Sum"}), new sap.ui.commons.TextField({value: "{TotalSum}", width: "100%", editable: false})); oLayout.createRow(new sap.ui.commons.Label({text: "Currency"}), new sap.ui.commons.TextField({value: "{Currency}", width: "100%", editable: false})); oLayout.createRow(new sap.ui.commons.Label({text: "Note"}), new sap.ui.commons.TextArea({value: "{Note}", width: "100%", editable: false})); // add the layout to the panel oPanel.addContent(oLayout); return oPanel; }

Now add the Sales Order Details view as child of the Sales Order List view:

Page 7: CD267 Exercise

7

createContent : function(oController) { […] // create and add the sales order details var oDetails = sap.ui.view({ id: this.createId("details"), viewName: "teched2012.SalesOrderDetails", type: sap.ui.core.mvc.ViewType.JS }); return [oTable, oDetails]; }

In the Sales Order List controller add a row selection change handler to the Table in the onInit function which

changes the binding context of the Sales Order Details view: onInit: function() { […] // listen to the row selection and update the details view var oDetails = this.byId("details"); oTable.attachRowSelectionChange(function(oEvent) { var oContext = oTable.isIndexSelected(oEvent.getParameter("rowIndex")) ? oEvent.getParameter("rowContext") : undefined; oDetails.setBindingContext(oContext); }); }

Now you have created a Master Detail screen based on Sales Orders fetched from an OData service. Your screen should look like this:

Page 8: CD267 Exercise

8

023_Add the UX3 shell to your application Now the SAP UX3 shell control will be added and the sales order list and detail will be embedded in the shell:

Import the sap.ui.ux3 library in the bootstrap tag in the index.html.

In the index.html page we create the Shell control and the Sales Orders working set and add the view as content of the Shell: var oShell = new sap.ui.ux3.Shell({ appTitle: "SAPUI5 Hands-On Session", showFeederTool: false, showInspectorTool: false, showSearchTool: false, showLogoutButton: false, worksetItems: [ new sap.ui.ux3.NavigationItem({text: "Sales Orders"}) ] }); sap.ui.localResources("teched2012"); var view = sap.ui.view({id:"idSalesOrderList1", viewName:"teched2012.SalesOrderList", type:sap.ui.core.mvc.ViewType.JS}); oShell.setContent(view); oShell.placeAt("content");

Now the application should look like this:

Page 9: CD267 Exercise

9

024_Displaying Order Items The next step will add the functionality to display the order items belonging to the selected order:

Create a new view via project context menu > New… > Other… > SAPUI5 Application Project > View and name it SalesOrderItems (the type is also JSON View) > Finish

In the createContent method of the View we create a Panel containing a Table with the following fields: ProductID, ProductName, Quantity in Pieces, Total Sum, Currency:

createContent : function(oController) { // Panel containing order details var oPanel = new sap.ui.commons.Panel({ id: this.createId("order_items_panel"), text: "Sales Order Items", width: "100%" }); var oTable = new sap.ui.table.Table({ id: this.createId("order_items_table"), selectionMode: sap.ui.table.SelectionMode.None, rowHeight: 30, visibleRowCount: 4, columns: [ new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "ProductID" }), template: new sap.ui.commons.TextView({ text: "{ProductID}" }) }), new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "ProductName" }), template: new sap.ui.commons.TextView({ text: "{ProductName}" }), sortProperty: "ProductName" }), new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "Quantity in pieces" }), template: new sap.ui.commons.TextView({ text: "{Quantity}" }), sortProperty: "Quantity" }), new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "TotalSum" }), template: new sap.ui.commons.TextView({ text: "{TotalSum}" }), sortProperty: "TotalSum" }), new sap.ui.table.Column({ label: new sap.ui.commons.Label({ text: "Currency" }), template: new sap.ui.commons.TextView({ text: "{Currency}" }), sortProperty: "Currency" }) ] }); oPanel.addContent(oTable); return oPanel; }

Page 10: CD267 Exercise

10

The next step is to bind the rows so that by later specifying the binding context we have a proper binding against the selected Sales Order in the upper list. To do so, open the controller and bind the rows of the Table against the SalesOrderItems collection:

onInit: function() { this.byId("order_items_table").bindRows("SalesOrderItems"); }

Now we extend the row selection change handler of the Sales Order List to also update the binding context of the Sales Order Items:

onInit: function() { […] // listen to the row selection and update the details view var oDetails = this.byId("details"); var oItems = this.byId("items"); oTable.attachRowSelectionChange(function(oEvent) { var oContext = oTable.isIndexSelected(oEvent.getParameter("rowIndex")) ? oEvent.getParameter("rowContext") : undefined; oDetails.setBindingContext(oContext); oItems.setBindingContext(oContext); }); }

The last step is to finally add the view into the Sales Order List view:

createContent : function(oController) {

[…] // create and add the sales order details var oDetails = sap.ui.view({ id: this.createId("details"), viewName: "teched2012.SalesOrderDetails", type: sap.ui.core.mvc.ViewType.JS }); // create and add the sales order items var oItems = sap.ui.view({ id: this.createId("items"), viewName: "teched2012.SalesOrderItems", type: sap.ui.core.mvc.ViewType.JS }); // put the views into a matrix layout var oLayout = new sap.ui.commons.layout.MatrixLayout({ rows: [ new sap.ui.commons.layout.MatrixLayoutRow({ cells: [ new sap.ui.commons.layout.MatrixLayoutCell({

Page 11: CD267 Exercise

11

vAlign: "Top", content: [oDetails] }), new sap.ui.commons.layout.MatrixLayoutCell({ vAlign: "Top", content: [oItems] }), ] }) ] }); return [oTable, oLayout]; }

Having completed this last step your UI will look like this:

Page 12: CD267 Exercise

12

03_Create a notepad chart control

To show the control extensibility of SAPUI5, a new “notepad” control is added to visualize sales order data as chart. A notepad control is a control whose definition and implementation is done inline as part of the application. It is so easily done you can use a simple text editor like notepad to write the control. This is where the name comes from! Using notepad controls one can add their own HTML elements and behaviors to a UI5 applications as well as including other JavaScript libraries. In a notepad control one has access to UI5 control standard functionalities like data binding and automatic rerendering in case of property changes.

030_Define the notepad control

In this section you will create a pie chart as a notepad control using a popular and powerful open source JavaScript library called D3.JS. It is freely available under a BSD license. The code to create the D3 pie chart used Ian Johnson’s work on github as a template, it is slightly adjusted to work in our new control. The notepad control will be put on a separate file in a new folder in our UI5 project.

Create a new folder under the “WebContent” folder in your project using the context menu and New > Folder. Name the folder “modules”

Create a new JavaScript file in the “modules” folder using the context menu and New -> File. Name the file “piechart.js”

In the file define a UI5 element chart.”ChartItem” for the individual pie pieces of our chart. The pie pieces will be labelled by the product name and an amount which indicates how big the piece is. Create these properties with a string type and no default value.

//chart items sap.ui.core.Element.extend("chart.ChartItem", { metadata : { properties : { "productid" : {type : "string", defaultValue : null}, "amount" : {type : "string", defaultValue : null} } }});

Add the control to the file below the element code. The control will have 2 properties text to set a text for the

entire pie chart and size to define the width and height of the chart in pixels. It also gets an aggregation items.

The type of the items aggregation is of the chart.ChartItem element

sap.ui.core.Control.extend("chart.Pie", { // the control API: metadata : {

properties : { // setter and getter are created behind the scenes, incl. data // binding and type validation

"text" : "string", // in simple cases, just define the type "size" : {type: "sap.ui.core.CSSSize", defaultValue: "200px"}

// you can also define a default value and more }, aggregations : { "items" : { type: "chart.ChartItem", multiple: true, singularName: "item"} }

}, //some other stuff goes in here later

031_Add the renderer method

Page 13: CD267 Exercise

13

A UI5 control usually creates some HTML elements and has behaviours like event handlers in JavaScript. In this section we will add the rendering of HTML to our chart control. As most JavaScript libraries D3.JS needs an HTML element as a container to add its own elements to. We therefore create a <div> element to become our container. The standard method in UI5 notepad controls to do this is called “renderer”.

Add the renderer method directly after the meta data object in the control, replacing the //some other stuff

goes here comment of the last section. Note the oRm object, the so called render manager. This object has a

couple of methods to add HTML elements and their properties to the control’s output. Also there is an oControl

object which allows access to the control’s properties and aggregations. Here we get the size property and use it

to set the width of the container. Note how the definition of a size property results in the control having a getSize

method (as well as a setSize method). These are automatically added by the UI5 runtime.

// the part creating the HTML: renderer : function(oRm, oControl) { // static function, so use the given "oControl" instance

// instead of "this" in the renderer function oRm.write("<div style='margin:0px auto 0px auto;width:"+oControl.getSize()+"'"); oRm.writeControlData(oControl); // writes the Control ID and enables event handling

// this important for UI5 to reckognize a control oRm.addClass("pie"); // add an optional CSS class for styles oRm.writeClasses(); // this call writes the above class oRm.write(">"); oRm.write("</div>"); }, //some other stuff goes in here later

031_Add the onAfterRendering method Like most other JavaScript libraries D3.JS adds own content to a given container. As soon D3’s methods are invoked they assume the container already to be exisiting in the HTML page’s DOM structure. However, when the UI5 control’s renderer method is invoked, its output isn’t directly put into the page’s DOM element by the UI5 runtime. This only happens at a defined later point in time, when other controls have also add their output. This however means that adding the D3 code directly into the renderer method we defined above would result in JavaScript errors in D3. We therefore have to place the D3 code into another standard method of UI5 controls, the so-called onAfterRendering method. Like its name is implied, it is only called by UI5’s runtime after the actual rendering has taken place, i.e. when the DOM elements are created

Add the onAfterRendering method directly after the renderer method, replacing the //some other stuff goes here comment of the last section. In this method one gets access to the control and its properties via the this

object. Here we get the text and the size properties. We also access the items aggregation and loop over the

items, extracting its data and putting it into a data array. This array will later be used to feed D3 methods with the

data.

onAfterRendering: function() { // this is called when the rendering of the HTML has actually // happened

//get the control property "size" and the aggregation "items" var iSize = parseInt(this.getSize()); var sText = this.getText(); var aItems = this.getItems(); var data = []; //get data and push it into an array suitable for D3 for (var i=0;i<aItems.length;i++){ var oEntry = {}; for (var j in aItems[i].mProperties) {

Page 14: CD267 Exercise

14

oEntry[j]=aItems[i].mProperties[j]; } data.push(oEntry); }

//some other stuff goes in here later

Add the following code directly after the lines of the last section replacing the //some other stuff goes here

comment. This is the heart of the control, the rendering of the pies using D3. Without going into the details of the D3 code – there are many tutorials and D3’s reference out there for this – D3 basically renders SVG elements and give one a number of functions to make displaying data easier: Providing most important building blocks like pies and bars, implicitly looping over and scaling data.

var w = iSize, //width h = iSize+20, //height r = iSize/2, //radius color = d3.scale.category20c(); //builtin range of colors color = function scale(x) {

var aCol = ["#0e304c","#efa900","#a6a6a6","#676767","#0560a8","#0e4076","#cc980d","#b68001","#fefefe"];

return aCol[x]; } var vis = d3.select("#"+this.getId()) //make container from our control known to D3

.append("svg:svg") //create the SVG element inside the <body> .data([data]) //associate our data with the document .attr("width", w) //set the width and height of our visualization (these

//will be attributes of the <svg> tag .attr("height", h) .append("svg:g") //make a group to hold our pie chart .attr("transform", "translate(" + r + "," + r + ")")

//move the center of the pie chart from 0, 0 to radius, radius var arc = d3.svg.arc() //this will create <path> elements for us using arc data .outerRadius(r); var pie = d3.layout.pie() //this will create arc data for us given a list of values .value(function(d) { return d.amount; }); //we must tell it out to access the value of

//each element in our data array

var arcs = vis.selectAll("g.slice") //this selects all <g> elements with class slice //(there aren't any yet)

.data(pie) //associate the generated pie data (an array of arcs, each having //startAngle, endAngle and value properties)

.enter() //this will create <g> elements for every "extra" data element that should //be associated with a selection. The result is creating a <g> for every //object in the data array

.append("svg:g") //create a group to hold each slice (we will have a <path> and a //<text> element associated with each slice)

.attr("class", "slice"); //allow us to style things in the slices (like text) arcs.append("svg:path") .attr("fill", function(d, i) { return color(i); } ) .attr("d", arc); //this creates the actual SVG path using the associated data (pie)

//with the arc drawing function arcs.append("svg:text") //add a label to each slice .attr("transform", function(d) { //set the label's origin to the center of the arc

Page 15: CD267 Exercise

15

d.innerRadius = 0; //we have to make sure to set these before calling arc.centroid d.outerRadius = r;

//this gives us a pair of coordinates like [50, 50] return "translate(" + arc.centroid(d) + ")"; })

.attr("text-anchor", "middle") //center the text on its origin .text(function(d, i) { //get the label from our original data array return data[i].productid; }).style("stroke", "#fff"); var title = vis.append("g") //set a title .attr("text-anchor", "end") .attr("transform", "translate(0,"+(iSize/2+20)+")"); title.append("text") .attr("class", "title") .text(sText); } });

04_USE THE NOTEPAD CONTROL WITHIN THE APPLICATION

In this section we will add our new pie chart control to the application and display the total sum for each order item in the chart. We will bind the control to the same order items collection from our model as we have done for the items table previously.

040_Adding the D3.JS library and the notepad control to the application

Select the index.html page of you project in the WebApplication folder. Add the reference to D3.JS public location, which will result in the D3 library being loaded into the application. To do so, add the following code underneath UI5’s bootstrap script tag and the comment to add other libraries:

[…] <!-- add sap.ui.table,sap.ui.ux3 and/or other libraries to 'data-sap-ui-libs' if required --> <script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.js?2.8.1"></script>

Still in index.html add the following code in red to the <script> block that defines the shell and the view. Place this directly above the shell definition code. This indicates to the UI5 runtime that all JavaScript modules in the namespace modules are to be found in a folder modules. Subsequently the require method loads the module file

that contains our pie chart […] <script> // redirect the 'modules' package to the local web app jQuery.sap.registerModulePath('modules', 'modules'); //this is a "Notepad Control": a Pie chart jQuery.sap.require("modules.piechart");

041_Create a sales order items chart view and controller As next step, a new view is added to display the sales order items pie chart:

Page 16: CD267 Exercise

16

Create a new view via project context menu > New… > Other… > SAPUI5 Application Project > View and name it SalesOrderItemChart, the type is JSON View. > Finish

Select the SalesOrderItemChart.view.js file. In the createContent function of the view we create a Panel control containing the pie chart. Then we create the pie chart from our notepad control. We bind its text to the id of the selected sale order and its items to the sales order items. The we add the pie to the panel and pass the panel to the view

createContent : function(oController) { // Panel containing order details var oPanel = new sap.ui.commons.Panel({ id: this.createId("order_itemes_chart_panel"), text: "Sales Order Items Chart", width: "100%" }); //add a pie chart var oPie = new chart.Pie({ id: this.createId("order_items_chart"), size: "200px", text: "{SalesOrderID}" }); // and now bind the pies to the line items also oPie.bindAggregation("items", { path: "SalesOrderItems", template : new chart.ChartItem(

{productid:"{ProductID}",amount:"{TotalSum}"} )

}); // add the layout to the panel oPanel.addContent(oPie); return oPanel; }

042_Adapt the sales order list view and controller As next step, the sales order list view is adapted to include the sales order items chart view and to bind the selected sales order to the chart:

Select the SalesOrderList.view.js file. In the createContent function of the view add the following lines in red which instantiates the new chart view. Place these lines just underneath the lines to create the items view (oItems) createContent : function(oController) {

[…]

// create and add the sales order items var oItems = sap.ui.view({ id: this.createId("items"), viewName: "teched2012.SalesOrderItems", type: sap.ui.core.mvc.ViewType.JS

}); // create and add the sales order items chart

var oItemsChart = sap.ui.view({ id: this.createId("itemschart"), viewName: "teched2012.SalesOrderItemsChart",

Page 17: CD267 Exercise

17

type: sap.ui.core.mvc.ViewType.JS

});

Still in the createContent function add the following red lines which add the new charts view to the matrix layout of

the application:

[…]

// put the views into a matrix layout var oLayout = new sap.ui.commons.layout.MatrixLayout({ rows: [ new sap.ui.commons.layout.MatrixLayoutRow({ cells: [ new sap.ui.commons.layout.MatrixLayoutCell({ vAlign: "Top", content: [oDetails] }), new sap.ui.commons.layout.MatrixLayoutCell({ vAlign: "Top", content: [oItems] }), new sap.ui.commons.layout.MatrixLayoutCell({ vAlign: "Top", content: [oItemsChart] }) ] }) ]

});

Select the SalesOrderList.controller.js file. Add the following lines in red to the controller’s onInit function. This is

to set the binding context for the chart to the selected sales order. onInit: function() {

[…]

// listen to the row selection and update the details view

var oDetails = this.byId("details"); var oItems = this.byId("items"); var oTemsChart = this.byId("itemschart"); oTable.attachRowSelectionChange(function(oEvent) { var oContext = oTable.isIndexSelected(oEvent.getParameter("rowIndex")) ? oEvent.getParameter("rowContext") : undefined; oDetails.setBindingContext(oContext); oItems.setBindingContext(oContext); oTemsChart.setBindingContext(oContext);

});

Having completed this last step your UI looks like this:

Page 18: CD267 Exercise

18

Page 19: CD267 Exercise

© 2012 by SAP AG. All rights reserved. SAP and the SAP logo are registered trademarks of SAP AG in Germany and other countries. Business Objects and the Business Objects logo are trademarks or registered trademarks of Business Objects Software Ltd. Business Objects is an SAP company. Sybase and the Sybase logo are registered trademarks of Sybase Inc. Sybase is an SAP company. Crossgate is a registered trademark of Crossgate AG in Germany and other countries. Crossgate is an SAP company.