Skip to Content

This blog post is at the request of Abesh Bhattacharjee – blame him πŸ˜‰


The SAPUI5 library includes chart controls based upon the VIZ charting library. You can see some samples of them in action at https://sapui5.hana.ondemand.com/sdk/test-resources/sap/viz/Charting.html

Once you start building charts you pretty soon want to implement some event handling when a user clicks on a chart element. For example the usual way of implementing drill-down is by having the user click on a chart element and then using that element as the context for subsequent processing – perhaps rendering another chart that shows a more granular representation of just the element selected.

The SAPUI5 eventing framework allows us to attach an handler to the selectData event to be called when a user clicks on a chart element. The framework passes a sap.ui.base.Event object to the handler that contains the details of the specific action and target that triggered the event. In a perfect world we would be able to extract from this object the context of the element we clicked on so we could use that for subsequent actions.

In simple charts that only have a single dimension and a single measure this is achievable – albeit not terribly easily. There is an example of how to do it Re: Need dimensions value on in VIZ bar Chart dataselect event.

But when you are charting multiple measurements and/or multiple dimensions things become much more difficult. Take for example this stacked column chart.

Screen Shot 2013-07-01 at 10.59.25 PM.png

If you want to follow along my example yourself here is the HTML/Javascript that created it.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Chart</title>
<script id="sap-ui-bootstrap" type="text/javascript"
  src="resources/sap-ui-core.js"
  data-sap-ui-libs="sap.ui.commons, sap.viz">
</script>
<script>
  var oModel = new sap.ui.model.json.JSONModel({
    data : [
      { country : 'China', product : 'Car', profit : 32 },
      { country : 'France', product : 'Car', profit : 43 },
      { country : 'Germany', product : 'Car', profit : 34 },
      { country : 'USA', product : 'Car', profit : 25 },
      { country : 'China', product : 'Truck', profit : 78 },
      { country : 'France', product : 'Truck', profit : 86 },
      { country : 'Germany', product : 'Truck', profit : 56 },
      { country : 'USA', product : 'Truck', profit : 76 },
      { country : 'China', product : 'Motorcycle', profit : 78 },
      { country : 'France', product : 'Motorcycle', profit : 86 },
      { country : 'Germany', product : 'Motorcycle', profit : 56 },
      { country : 'USA', product : 'Motorcycle', profit : 76 },
      { country : 'China', product : 'Bicycle', profit : 78 },
      { country : 'France', product : 'Bicycle', profit : 86 },
      { country : 'Germany', product : 'Bicycle', profit : 56 },
      { country : 'USA', product : 'Bicycle', profit : 76 }
    ]
  });
  sap.ui.getCore().setModel(oModel);
  var dataset = new sap.viz.ui5.data.FlattenedDataset({
    dimensions : [
      { axis : 1, name : 'Country', value : "{country}" },
      { axis : 2, name : 'Product', value : "{product}" }
    ],
    measures : [
      { name : 'Profit', value : '{profit}' }
    ],
    data : { path : "/data" }
  });
  new sap.viz.ui5.StackedColumn("oChart",{
    width : "100%",
    height : "200px",
    title : { visible : true, text : 'Test Stacked Column Chart' },
    dataset : dataset
  }).placeAt("content");
</script>
</head>
<body class="sapUiBody">
  <div id="content"></div>
</body>
</html>

Notice that we have two dimensions – Country and Product. We can select an individual element by clicking on it, we can select an entire column by clicking on the X-axis label, and we can select many elements together.

Screen Shot 2013-07-01 at 11.00.27 PM.png

Each time we click a chart element we fire the selectData event which passes details of the element we clicked on to any event handlers. The challenge is to determine the context of this element for subsequent processing. What follows is one way you could do this by adding a few lines of javascript to the HTML page.

Step 1. Turn off all the user interaction that the chart library delivered with the exception of tooltips.

  sap.ui.getCore().byId("oChart").setInteraction(
    new sap.viz.ui5.types.controller.Interaction({
      selectability: new sap.viz.ui5.types.controller.Interaction_selectability({
        mode: sap.viz.ui5.types.controller.Interaction_selectability_mode.none
      })
    })
  );

Step 2. Attach an event handler for the browser click event to the chart.

  sap.ui.getCore().byId("oChart").attachBrowserEvent("click",chartClickHandler);

Step 3: Implement the event handler.

We are only interested in clicks on the x-Axis of the chart. The x-Axis markup is wrapped in a SVG tag that looks like <g class=”v-m-xAxis” …>. So firstly we test to see if the area clicked is not a descendant of his tag and return immediately.

if(!$(oEvent.srcElement).closest('.v-m-xAxis').length) return;

The x-Axis labels are rendered like the below sample. The <rect> tag is the source element of the click event.

<rect x=”301″ y=”1″ width=”301″ height=”35″ opacity=”0″ class=”v-labelarea” fill=”#808080″></rect>

<g fill=”#333333″ class=”v-label viz-axis-label” font-size=”12px” font-weight=”normal” font-family=”‘Open Sans’, Arial, Helvetica, sans-serif”>

  <text pointer-events=”none” x=”452″ y=”18.2″ dominant-baseline=”middle” text-anchor=”middle”>France</text>

</g>

We can isolate the contents of the <text> tag into a variable called xAxisLabel like this.

    var xAxisLabel=$($(oEvent.srcElement).next('.viz-axis-label').children('text')).text();

If I add a dialog box to confirm the x-Axis label that has been clicked the complete event handler looks like this.

  function chartClickHandler(oEvent) {
    if(!$(oEvent.srcElement).closest('.v-m-xAxis').length) return;
    var xAxisLabel=$($(oEvent.srcElement).next('.viz-axis-label').children('text')).text();
    new sap.ui.commons.Dialog({ title: xAxisLabel+" clicked" }).open();
  }

It’s not a perfect solution but it works for our example. Obviously the more complex the chart the more challenging isolating the context of a user click event will be.

Screen Shot 2013-07-01 at 11.01.20 PM.png

If, like me, you are amazed at what can be done with a few lines of Javascript I encourage you to check out JQuery.

And just for completeness here is the final version.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Chart</title>
<script id="sap-ui-bootstrap" type="text/javascript"
  src="resources/sap-ui-core.js"
  data-sap-ui-theme="sap_goldreflection"
  data-sap-ui-libs="sap.ui.commons, sap.viz">
</script>
<script>
  var oModel = new sap.ui.model.json.JSONModel({
    data : [
      { country : 'China', product : 'Car', profit : 32 },
      { country : 'France', product : 'Car', profit : 43 },
      { country : 'Germany', product : 'Car', profit : 34 },
      { country : 'USA', product : 'Car', profit : 25 },
      { country : 'China', product : 'Truck', profit : 78 },
      { country : 'France', product : 'Truck', profit : 86 },
      { country : 'Germany', product : 'Truck', profit : 56 },
      { country : 'USA', product : 'Truck', profit : 76 },
      { country : 'China', product : 'Motorcycle', profit : 78 },
      { country : 'France', product : 'Motorcycle', profit : 86 },
      { country : 'Germany', product : 'Motorcycle', profit : 56 },
      { country : 'USA', product : 'Motorcycle', profit : 76 },
      { country : 'China', product : 'Bicycle', profit : 78 },
      { country : 'France', product : 'Bicycle', profit : 86 },
      { country : 'Germany', product : 'Bicycle', profit : 56 },
      { country : 'USA', product : 'Bicycle', profit : 76 }
    ]
  });
  sap.ui.getCore().setModel(oModel);
  var dataset = new sap.viz.ui5.data.FlattenedDataset({
    dimensions : [
      { axis : 1, name : 'Country', value : "{country}" },
      { axis : 2, name : 'Product', value : "{product}" }
    ],
    measures : [
      { name : 'Profit', value : '{profit}' }
    ],
    data : { path : "/data" }
  });
  new sap.viz.ui5.StackedColumn("oChart",{
    width : "100%",
    height : "200px",
    title : { visible : true, text : 'Test Stacked Column Chart' },
    dataset : dataset
  }).placeAt("content");
//Step 1. Turn off all the user interaction stuff in the chart apart from tooltips.
  sap.ui.getCore().byId("oChart").setInteraction(
    new sap.viz.ui5.types.controller.Interaction({
      selectability: new sap.viz.ui5.types.controller.Interaction_selectability({
        mode: sap.viz.ui5.types.controller.Interaction_selectability_mode.none
      })
    })
  );
//Step 2. Attach an event handler for when the user clicks on the chart.
  sap.ui.getCore().byId("oChart").attachBrowserEvent("click",chartClickHandler);
//Step 3. Implementation of the event handler.
  function chartClickHandler(oEvent) {
    if(!$(oEvent.srcElement).closest('.v-m-xAxis').length) return;
    var xAxisLabel=$($(oEvent.srcElement).next('.viz-axis-label').children('text')).text();
    new sap.ui.commons.Dialog({ title: xAxisLabel+" clicked" }).open();
  }
</script>
</head>
<body class="sapUiBody">
  <div id="content"></div>
</body>
</html>

Cheers

Graham Robbo

To report this post you need to login first.

61 Comments

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

  1. Abesh Bhattacharjee

    Robbo, thanks so much for blogging this !

    I am sure others will find it as useful as I have, without wasting the numerous hours chasing a solution to a feature missing in action !

    YOU ROCK !!!

    (0) 
  2. Bibhas Das

    Hi, thank you so much for acknowledging my simple solution into your wonderful blog. You are one of my most admired person and inspired me a lot.

    Thanks

       &

    Best Regards,

    Bibhas Das

    (0) 
  3. Atul Agrawal

    Hi Graham,

    Thank you for the wonderful Blog.

    I am facing a problem while using the same on vbox. Is this not supposed to work if I put my chart inside a vbox and then call setinteraction?

    I am getting

    Uncaught TypeError: Cannot call method ‘setInteraction’ of undefined

    Can you guide me what I might be doing wrong?

    (0) 
    1. Graham Robinson Post author

      Hi Atul,

      you have a javascript error – it looks like the object you are trying to call the setinteraction method on is not being found.

      Jump into a javascript debugger and see what it really happening.

      (0) 
  4. Flavien Breton

    Hi Graham,

    Thank you for you blog, it is very usefull for me, I’m a beginner in SAPUI5.

    When I perform your example I don’t have the popup, the condition in the function doesn’t pass. So I can’t trigger the click in the X-axis label.

    Do you have an idea about why ? Am I the only one this that problem ?

    (0) 
    1. Graham Robinson Post author

      Hi Flavien,

      this solution relies upon the DOM that is created by the VIZ Chart.

      It appears this has changed slightly in the later versions of the SAPUI5 library.

      I found changing the charClickHandler function, as follows, works with the latest version of the SAPUI5 library.

          function chartClickHandler(oEvent) { 

            if(!$(oEvent.target).closest(‘.viz-axis-body’).length) return;

            var xAxisLabel=$($(oEvent.target).next(‘.viz-axis-label’).children(‘text’)).text();

            new sap.ui.commons.Dialog({ title: xAxisLabel+” clicked” }).open();

      Cheers

      Graham Robbo

      (0) 
  5. Deepak Sharma

    Hi Graham,

    Wonderful Blog. It helped me a lot to learn to create a column chart as i am new to UI5.

    But i have one question that instead of clicking any axis, i want to attach an event with the column of column chart. Could you please help me in achieving it??

    (0) 
    1. Graham Robinson Post author

      Hi Deepak,

      I see no reason why you couldn’t do this. The SAPUI5 library already supports this with simple charts. For more complex I encourage you to have a go and then blog about it to let everyone else know how to do it.

      Cheers

      Graham Robbo

      (0) 
      1. David Loop

        Hi Graham,

        Do you know the reason why sap.viz, docs and the examples are so hard to find?  I’m not exactly sure how to jump through those hoops you mentioned…

        David

        (0) 
      1. A K

        Hi Graham Robinson,

        Thanks for you reply.

        i have some open questions on this sap.viz.

        1. SAP.VIZ is it available for mobile run time library?

        2. sap.ui.suite.commons.TimeLine also not available in Mobile run time library.

        why SAP includes this two components in sap.Explored, i am little bit confused. πŸ˜•

        If you have any ref link, please guide me on this controls, for mobile/Tablet.

        for Desktop: this controls are working fine.

        Thanks,

        Karthik A

        (0) 
        1. Graham Robinson Post author

          Hi Karthik,

          these libraries are constantly being enhanced, updated and modified. You will have to sort out what works best for your particular needs. And remember there is no reason you can’t also incorporate other non-SAP libraries and components as well if you want to – or enhance the ones that SAP delivers.

          Cheers

          Graham Robbo

          (0) 
  6. Amit Singh

    Hi Graham,

    Thanks for a wonderful blog.

    I wanted to know if it is possible to create a 3-dimensional graph using SAP Ui5. If yes, Do we have any Demo available illustrating it?

    Regards,

    Amit

    (0) 
    1. Graham Robinson Post author

      Hi Amit,

      the answer to your questions is really “yes” and “no”. 😏

      Firstly it is important to remember that the SAPUI5 framework is designed so that it can properly co-exist with other libraries you may wish to use in your application.

      The sap.viz library I used for this example uses the open source D3.js library which can produce amazing data-driven visualisations. The sap.viz library only includes a limited list of 2D charts but there is no reason you couldn’t use the D3.js library (or any other library you prefer) to visualise your data any way you like in a SAPUI5 application.

      There are also other features of the SAPUI5 library designed to support SAP Visual Business, etc. and SAP deliver controls that provide charts using the MaKit library that have a more 3D look to them and are designed for mobile platforms. Demo here.

      Cheers

      Graham Robbo

      (0) 
  7. Naveen Kumar

    Hi Graham,

    Its a great blog with wonderful working sample. I appreciate for the post.

    I have an requirement to create a sample dashboard with drill down and filter functionality using sapui5 and html , getting input data from information models created in Hana.

    This post helps me to understand the base requirements for drill down feature.

    Can you help with a working sample or suggest some blog, for drill down and filter functionalities getting input data from models created in Hana?

    Thanks,

    Naveen


    (0) 
  8. Roger Li

    Hi Graham,


    currently i am using sap.viz.ui5.TimeBubble, my problem is when user click on one bubble, it is highlighted but if  one more click on this bubble nothing happened. what i expect is dismiss highlight. do you know any event about this?


    thanks in advance..

    (0) 
    1. Graham Robinson Post author

      Hi Roger,

      I haven’t looked at this library in a while so I am unable to directly answer your question, but I note in the documentation for the TimeBubble control there are events for both selectData and deselectData.

      You may be able to use these events to achieve what you want?

      Cheers

      Graham Robbo

      (0) 
      1. Roger Li

        it doesn’t work, because selectData is just called once when clicks on a chart element. if click again on this chart element, nothing happened. What i wanna do is if second click happens on this chart element, this element change its status from highlight to normal.

        i think it is general problem for all the viz chart.

        (0) 
          1. Roger Li

            definitely it  should work, somehow it is not entire solution. See if one “.v-datashape” is selected, its css changed a little bit as following I marked in bold,

            <g class=”v-datashape” transform=”translate(432.94955356928574,164.9029)”><path class=”v-datapoint v-morphable-datapoint v-datapoint-selected” fill=”#68cbe7″ stroke-width=”1″ stroke=”#498ea2” stroke-opacity=”0.8″ d=”M-33.5,0 A33.5,33.5 0 1,0 33.5,0 A33.5,33.5 0 1,0 -33.5,0z” fill-opacity=”0.8″></path></g>

            and the other datashapes changed to ,

            <g class=”v-datashape” transform……….

            <path class=”v-datapoint-default v-datapoint v-morphable-datapoint” fill=”#ffcd84″ stroke-width=”1″ stroke=”#ffffff” stroke-opacity=”0.4” d=”M-34.5,0 A34.5,34.5 0 1,0 34.5,0 A34.5,34.5 0 1,0 -34.5,0z” fill-opacity=”0.4“></path></g>


            for dismiss highlight, i don’t want to loop all the v-datashapes to change their css. is there any build-in api to do that

            (0) 
              1. Roger Li

                the one that clicked is highlighted, the other ones are gray out… i have to loop through to change the CSS back…that’s  the reason why i wanna find a elegant way.

                (0) 
  9. Ruven Spiller

    Hey,

    I’m using xml-Views and try to attach a event to a column click inside a colum-chart.

    I tried to use the “handlers”-Attribute, but it always states the given function is undefined.

    <vtc:Interaction supportedEventNames=”mouseup,mousedown,mousemove,mouseout,mouseover,touchstart” handlers=”chartClick”>


    </vtc:Interaction>

    Since im using as much in the XML-Views/Fragments as possible, I would like to avoid getting the id an attach browser events.

    Is there a way to attach such handlers via xml?

    (0) 
    1. Venkatesh Sora

      Hi Ruven.

      Good Day.

      Have you found any solution for it? Let me know the definition structure if you have done so? Share the solution thread if any.

      I am trying to use the i5Charts in XML view but couldn’t find any code samples on the same. Let me know if you have any clue.

      Thanks

      Venkatesh πŸ™‚

      (0) 
  10. Ranajay Sit

    Hey

      //Step 1. Turn off all the user interaction stuff in the chart apart from tooltips. 

                                sap.ui.getCore().byId(“priceByPaymentType”).setInteraction( 

                                 new sap.viz.ui5.types.controller.Interaction({ 

                                 selectability: new sap.viz.ui5.types.controller.Interaction_selectability({ 

                                 mode: sap.viz.ui5.types.controller.Interaction_selectability_mode.none  

                                    }) 

                                 }) 

                              ); 

                    //Step 2. Attach an event handler for when the user clicks on the chart. 

                                 sap.ui.getCore().byId(“priceByPaymentType”).attachBrowserEvent(“click”,chartClickHandler); 

                    //Step 3. Implementation of the event handler. 

                            

                               function chartClickHandler(oEvent) {

                                if(!$(oEvent.target).closest(‘.viz-axis-body’).length) return;

                                var xAxisLabel=$($(oEvent.target).next(‘.viz-axis-label’).children(‘text’)).text();

                                new sap.ui.commons.Dialog({ title: xAxisLabel+” clicked” }).open();

                                }  

    the above code i used for my application. Step1 works fine. but on click event action is not working.

    (0) 
    1. Graham Robinson Post author

      Hi Ranajay,

      this code depends on the underlying SAPUI5 libraries which are regularly updated – and each update potentially changes how the chart is rendered. This means you will need to adjust the code to match the rendered HTML. Check earlier comments for an example.

      Cheers

      Graham Robbo

      (0) 
  11. Joseph BERTHE

    Hello,

    thanks for your blog. But after searching a nicer way I found the solution to get data selected :

    In selectedData handler :

    var oSelectData = oEvent.getParameter(“data”);
    var oVizFrame = this.getView().byId(“idVizFramePie”);
    var oContext = oVizFrame.getDataset().findContext(oSelectData[0].data[0].ctx.path);
    alert(“Selection” + oContext.getPath());

    This should be more flexible.

    Regards

    (0) 
    1. Filip Perisic

      Hi Joseph,

      could you please give a bit more details about your solution?

      Given a following example, where to put selectData handler?

      sap.ui.define([

             …

             …

          ], function(Controller,..) {

          “use strict”;

      var PieController Controller.extend(“my.namespace.PieChart”, {

        onInit : function(oEvent) {…},

        onBeforeRendering : function() {},

        onAfterRendering : function() {}

          });

          return PieController;

      });

      Kind regards,

      Filip

      (0) 
      1. Joseph BERTHE

        Hello,

        In the XML view :

        <viz:ui5.controls.VizFrame id=”idVizFramePie” selectData=”.onSelectedDataPie

        uiConfig=”{applicationSet:’fiori’}” vizType=”column”  width=”1000px”></viz:ui5.controls.VizFrame>

        In the controller :

        onSelectedDataPie:function(oEvent) {
        // get the event data as provided by the native sap.viz librarycontext_row_number
        var iSelectDataIndex = oEvent.getParameter(“data”)[0].data._context_row_number;
        var oVizFrame = this.getView().byId(“idVizFramePie”);
        var oData = oVizFrame.getDataset().getModel().getData().results[iSelectDataIndex];
        this._updateItemListModel(oData);
        },

        Hope it will help you.

        Regards,

        (0) 
  12. Filip Perisic

    Thanks Graham for this blog post, it explains well how to achieve desired goal.

    Following your example, I have wrote the handler that isolates the context of a user click event for PieChart. Maybe someone finds it useful.

    var pieChartClickHandler = function(oEvent){

             

       var target = oEvent.srcElement || oEvent.target;

             

       if(!$(target).closest(‘.v-datapoint’).length)

             return;

                 

       var clickedElementId = target.parentElement.getAttribute(“data-datapoint-id”);

       var clickedElementLabel = $(“.v-datalabel[data-datapoint-id='” + clickedElementId +”‘]”).children(‘text’).text();

               

      console.log(“Clicked Data: ” + clickedElementLabel);

    };

    Best regards,

    Filip

    (0) 
    1. Graham Robinson Post author

      Hi Filip,

      I think you might have missed an important piece of information contained within the comments for this blog.

      Please remember that this blog was written more than 2 years ago when trapping and interpreting events from the Viz charts was very rudimentary. Since then the libraries have been enhanced many times and now there is much better event handling interpretation built into the controls.

      Joseph BERTHE has pointed to some of these new event handlers in his comments.

      The key thing is that if the SAP delivered controls come with suitable event handling we should use it – and not build our own in the way I did originally with this example. That is because SAP will ensure these event handlers continue to work properly even if they make changes to the DOM representation of the controls.

      When the controls change the way they are rendered jQuery-based queries, such as $(target).closest('v-datapoint'), may no longer work or might point to a different result. This is why my solution has required changes several times since it was first published to accommodate the newer SAPUI5 libraries.

      I have built a newer example based upon the “selectData” and “deselectData” events of the sap.viz.ui5.controls.Vizframe control. You can see it in action at http://embed.plnkr.co/U9lkJmNetAknLrSI1HFK/

      Using the standard event handlers you can see how even selecting and deselecting columns of the chart in groups can be handled smoothly. The same principles can be applied to your pie chart example too – as users are able to select and deselect multiple segments at once.

        onSelectData: function(oEvent) {

          var aSelections = oEvent.getParameter("data");

          var oModel = this.getView().byId('idList').getModel();

          for (var i = 0; i < aSelections.length; i++) {

            this._selectedData.push(aSelections[i].data);

          };

          oModel.refresh();

        },

       

        onDeselectData: function(oEvent) {

          var aSelections = oEvent.getParameter("data");

          var oModel = this.getView().byId('idList').getModel();

          for (var i = 0; i < aSelections.length; i++) {

            for (var j = 0; j < oModel.getData().length; j++) {

              if (oModel.getData()[j] === aSelections[i].data) {

                oModel.getData().splice(j, 1);

                break;

              }

            };

          };

          oModel.refresh();

        }

      The below image shows it in action

      /wp-content/uploads/2015/12/vizevent_845430.gif

      I hope this helps.

      Cheers

      Graham Robbo

      (0) 
      1. Filip Perisic

        Hi Graham,

        thank you a lot for this nice explanation and code example. It’s easy to understand and suitable for UI5 beginners like me..your post made my life easier πŸ™‚ IMHO your example would be perfect for SAPUI5 Explored


        Kind regards,

        Filip

        (0) 
    2. Graham Robinson Post author

      Hi Filip,

      I finally found the notice I was looking for to include in my previous comment.

      Screen Shot 2015-12-06 at 10.57.59 AM.png

      As you can see the the control library I used in the original post 2 years ago has been deprecated and sap recommends using the VizFrame control instead. That is how I built the demo I linked to above.

      Cheers

      Graham Robbo

      (0) 
  13. Matheus Oliveira Goulart

    Hello Graham, greatΒ blog!

    I have a requirement to develop a gauge chart, and i know that it’s possible to do it with external libraries. My problem is that my application has to run on FIORI launchpad, and i do not found any post teaching how to use external libraries inside FIORI Launchpad.

    Do you have any idea if is this possible?

    Thanks!
    Matheus Goulart

    (0) 

Leave a Reply