Skip to Content

In my last blog I described how you could use open source tools to give you more control and flexibility on how to develop your code and what tools to use. Opensource is awesome and all but unfortunetely, unlike SAPUI5, OpenUI5 doesn’t have the closed source sap.Viz library to help make those fancy analytical apps. Even if you are working with SAPUI5, VizFrame is closed source if you don’t like it’s behavior… you can’t do anything about it.

A little DIY

charts.PNG


The next logical step was of course to create an open source library myself 🙂 that I called SimpleCharts.


You can add it to your project with the following command (assuming you have bower installed):

– bower install openui5-simplecharts

Then in your project you just need to add the following code to Component.js:


sap.ui.getCore().loadLibrary("openui5.simplecharts", "./bower_components/openui5/simplecharts/");
jQuery.sap.registerModulePath('bower_component', './bower_components');



















If you want to use the map plot, add the Leaflet library to index.html:


<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
 <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>







And there you go. After this, creating a chart is as simple as creating a dataset and a chart (it is loaded as library so you don’t need “jQuery.sap.require”):


var chartData = new openui5.simplecharts.SimpleChartData();
var data = { items: [ { "team": "Benfica", "goals":20 } , { "team": "Porto", "goals":15 } ] };
chartData.bindDimensions({ items : [ { name: "team", description:"Team", axis: "x"} ] };
chartData.bindMeasures({ items : [ { name: "goals", description:"Goals", rank: "1"}]});
chartData.bindData(data);
var chart = new openui5.simplecharts.SimpleBarChart({ title: "Goals by Team"});
chart.setData(chartData);



















You can also declare the chart in XML by referencing openui5.simplecharts which is loaded as a UI5 library. There is a BarChart, LineChart, PieChart, StackedBarChart and MapPlot (which is based on leaflet), and you can get more detail from the JSDocs. I won’t go into much detail because the purpose of the exercice was to learn, not to dump a library chart on SCN, so here’s what I learned along the way:

D3.js is just …. WOW

It’s incredible how such a great library like d3.js (Data-Driven-Documents) is available for free, and we can thank Mike Bostock for giving us this gem. For those who don’t know d3.js, it is a DOM manipulation library focused on Scaled Vector Graphics (SVG). Not only did Mike create d3.js, he created many examples of charts to guide your development. I used them to create all the charts except the MapPlot so this is more Mike’s work then mine.

To learn about D3.js there is this free book which I almost bought. I really recommend you read it, because while looking at examples is ok, only after reading the book was I able to really understand all commands and create a chart without looking at an example. Well worth it, and free!

I hope the source code available on Github will help you learn d3.js in the context of OpenUI5. Fork all you want, because like I said this was a learning journey, it’s not my objective to become a maintainer (I will make ajustments to keep learning, but unfortunately I don’t have enough time for it).

In the end, after creating all these charts, I found the NVD3.js library which has a set of pre-build charts based on D3.js. While the purpose of the exercice was to learn D3.js, if all you want is to make some charts you should check it out.

Maps for free!

As much as I love Google Maps and Mapbox, they aren’t free and I wanted to make a bubble chart over a map. I soon discovered Mapbox’s JS library is built on Leaflet (actually the Leaflet creater joined Mapbox), and if you can accept uglier maps, you can use this library combined with OpenStreetMaps for free (or you can just fork it and replace OSM with Mapbox). You can check the SimpleMapPlot.js file to see how I did it.

I was going to use a D3.js on a Leaflet layer to draw the chart itself, but for simple bubble charts that’s not necessary since you can use L.CircleMarker to draw the circles you see in the screenshot and Leaflet accepts longitude and latitude coordinates directly. I ended up using D3 scales for the bubble size, so that it adjusts to the window size of the map.

Building the library

Another challenge was to create a openui5 library so that it worked as any other native library (i.e sap.m), which meant following this library page of the OpenUI5 project and looking at what John Patterson had done in Google Maps library for UI5. This is the last section and it was the last thing I did, but … I shouldn’t have. Libraries must follow a specific signature so I had to refactor all the code (lesson learned).

The thing I had more trouble with was the CSS and the themes. I didn’t know anything about LESS but the OpenUI5 build uses it so I had to learn. It’s cool (basically CSS with variables) but if you don’t want to bother, just rename your .css to .less since CSS is a subset of LESS.

Finally I wanted to build the library so I could grab the library-preload.js. I tried to understand the preload on Optimizing OpenUI5/SAPUI5 Apps but ultimately failed and took the easy way out … I used the OpenUI5 project build. You can clone it using git, and then you add your project to the folder stucture. If you followed the rules on the library page this is straighforward. Just don’t forget to add your project themes/less to the theme folders at the bottom (don’t know why but blue_crystal has a separated folder in the project).

All that is left is to open the gruntfile.js of the OpenUI5 project, add your library to the build, run “grunt build” and after a few minutes you will get the library-preload.js (and the library.css) in the “target” folder.

Conclusion

The main thing I hope you take away from this blog, is that there are tools out that will enable you to do anything you want. In the age of Real-Time and the Internet of Things don’t restrict yourself to end-user frameworks that exist. If you have a vision (and the time) you can build it yourself!

To report this post you need to login first.

3 Comments

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

  1. JORGE ESPINOZA

    Good job. But I have a problem. I download your sources and running Example TESTGRAPH (/sample/testgraph/index.html) I get an error.

    SimpleBarChart.js:141 Uncaught TypeError: d3.tip is not a functionSimpleBarChart._drawGraph @ SimpleBarChart.js:141SimpleBarChart.onAfterRendering @ SimpleBarChart.js:405a._handleEvent @ sap-ui-core.js:974f @ sap-ui-core.js:1111R.flush @ sap-ui-core.js:1112R.render @ sap-ui-core.js:1113U.rerender @ sap-ui-core.js:1199v.renderPendingUIUpdates @ sap-ui-core.js:894v.init @ sap-ui-core.js:856v.handleLoad @ sap-ui-core.js:862(anonymous function) @ sap-ui-core.js:838l @ sap-ui-core.js:172S.finishTask @ sap-ui-core.js:172(anonymous function) @ sap-ui-core.js:838p @ sap-ui-core.js:126fireWith @ sap-ui-core.js:126ready @ sap-ui-core.js:126V @ sap-ui-core.js:126

    datajs.js:17 GET file:///sap/opu/odata/sap/$metadata net::ERR_FILE_NOT_FOUNDrequest @ datajs.js:17E2 @ datajs.js:17o.request @ datajs.js:17(anonymous function) @ library-preload.js:1864a._loadMetadata @ library-preload.js:1864constructor @ library-preload.js:1860constructor @ library-preload.js:1899o @ sap-ui-core.js:393init @ Component.js:73(anonymous function) @ sap-ui-core.js:461constructor @ sap-ui-core.js:461constructor @ sap-ui-core.js:661constructor @ library-preload.js:522f @ sap-ui-core.js:638e @ sap-ui-core.js:684sap.ui.component @ sap-ui-core.js:684createAndSetComponent @ library-preload.js:89c.onBeforeRendering @ library-preload.js:89a._handleEvent @ sap-ui-core.js:974t @ sap-ui-core.js:1107R.renderControl @ sap-ui-core.js:1109(anonymous function) @ sap-ui-core.js:457S.render @ library-preload.js:4339R.renderControl @ sap-ui-core.js:1109R.render @ sap-ui-core.js:1113U.rerender @ sap-ui-core.js:1199v.renderPendingUIUpdates @ sap-ui-core.js:894v.init @ sap-ui-core.js:856v.handleLoad @ sap-ui-core.js:862(anonymous function) @ sap-ui-core.js:838l @ sap-ui-core.js:172S.finishTask @ sap-ui-core.js:172(anonymous function) @ sap-ui-core.js:838p @ sap-ui-core.js:126fireWith @ sap-ui-core.js:126ready @ sap-ui-core.js:126V @ sap-ui-core.js:126

    (0) 

Leave a Reply