Working with Kendo UI controls in SAPUI5
Every once in a while, you may find yourself wanting to stretch the visual limits of SAPUI5. Luckily, SAPUI5 provides the option of using other controls libraries. In principle, this should be fairly straight-forward. Some of the 3rd party control libraries are even built on JQuery, and thus share the same foundation as UI5. Including them in your UI5 app should in principle be easy.
This blog aims to provide a walkthrough of challenges and pitfalls related to using controls from the Kendo UI framework in SAPUI5. I will focus on some simple chart implementations, and show how to use these in XML views. Also, I will show how to feed remote data into the chart controls, using OData.
Note: some of the code screenshots may be difficult to read; please click them in order to enlarge!
The following example has been created using the Web IDE on the HANA Cloud Platform – HCP. In the Web IDE, select New->Project from template->SAPUI5 Application. This gives you a simple UI5 application with one view (which should be of type XML).
This is the folder structure with the Kendo JS and CSS libraries:
Creating the simple app
We’ll create a simple app based on a sample OData service, and implement a Kendo chart control to visualize the data. The Kendo chart control provides a wide range of different chart types; I will show a couple of these. The functionality is similar – once you implement one, you can easily switch to another.
The OData service resides on a Netweaver Gateway system. For the purpose of illustration, I have created a simple table that shows the distribution of zombie observations across the US. (Another distinct advantage of using zombies is the fact that zombie starts with the letter “Z”, which makes it particularly useful for creating custom SAP objects like “zombietable”.)
The OData service based on my zombie table is created in the Gateway Builder (transaction SEGW). This is outside the scope of this blog; there’s an excellent book from SAP Press dealing with these topics.
The resulting metadata of my OData service (extract):
And part of the resulting ZombieSet record set:
With our OData service set up and running, it’s time to do the fun stuff: the Kendo in UI5 application.
The UI5 application
If we follow the wizard’s recommendations, we’ll end up having one initial view called “View1” with a related controller.
Our XMLview file will be quite simple. All it contains is a “div” element which holds our Kendo chart (and another div to encapsulate it). This is the code:
That’s it – really. I promise the controller will be a bit more complicated!
Kendo source code
Both of these hurdles require some tweaking of the Kendo code.
Let’s look at the standard Kendo code for a bar chart:
This is an excerpt. As we can see, the data source here is a JSON model. This will not work for us; we receive our remote data in OData format, and what we need to do is convert this into JSON.
Luckily, this is easy enough with SAPUI5 – we’ll see that in a minute.
Here is the controller code, section by section.
The main part here contains the onAfterRendering method. This is where we invoke the Kendo script – we do this after SAPUI5 has finished the general rendering of the view, that is, built all the standard UI5 framework elements.
We start by declaring our OData service url, and the path to the relevant record set within this service.
We then define a variable for the OData model.
Then, we set the scope variable that equal to this. “this” is a reference to the current scope, or “where we are now” in layman’s terms. By defining a new variable “that” and aligning it with “this”, we can refer to the createChart function inside the “success” callback function for our oDataModel.read logic. OK, this might seem complex (as promised), but the main idea is that we need to keep a reference to “where” we can retrieve the createChart function. Without using the “that” variable, we will loose sight of it within the “success” function, since we will have another scope there – “this” will not refer to the context where createChart is defined anymore.
It’s a bit like going through a wormhole to another universe, and trying to find Andromeda by looking at the sky. Won’t work. By declaring “that” before going, and taking it with you, you won’t be lost.
What goes on inside the “success” function – which is only invoked if the read of the OData model succeeds – is that we call the createChart function (I’ll get to it in a minute), then invoke a couple of Kendo-related commands that adds attributes to the finished chart.
The next part of our controller contains the actual Kendo chart function:
This is almost a copy/paste of the code from the Kendo samples site. The only things changed are the variable names (ZombieNumber and ZombieCity, from our OData model), as well as the “selector” – which actually warrants a section of its own. Finally, the specification of our data source and schema, which is also explained in detail below.
Use of selectors in Kendo code
Kendo JS is based on JQuery, and uses “selectors” in order to identify page elements. Selectors are a key concept in JQuery (and thus SAPUI5) – this is worth reading up on. As in “the following section won’t make much sense if you don’t know what a selector is”. I’ve provided a link to some excellent info further down.
Anyway, this whole selector thing poses a specific challenge when working with SAPUI5 XML views. In these views, the element id’s are “amended” by SAPUI5 on rendering. What happens is that the view name is added as a prefix to the element id, in order to uniquely define elements across views. Here is an example:
In our Kendo chart, the “div” element is named “chart”, as seen below:
This is the start of the createChart function, as retrieved from the Kendo sample site. As we can see, the function starts by using a selector identifying the “chart” element in our XML page. What happens if we use the code with the selector “as-is”?
The chart will not appear. This is because of the re-naming of our div element by the SAPUI5 rendering. If we look at the debugger, we can expand the elements to find our div:
As can be seen, SAPUI5 prefixes the element id with two underscores, followed by the view name (which, by the way, does not correspond to the actual view name as given by us; SAPUI5 generates brand new view names following the convention “xmlviewN”, where N is a number starting with 0), then two dashes, then finally our given id for the chart. Thus, “chart” in “View1” becomes “__xmlview0—chart”.
What we need to do, is tweak the Kendo code to correspond to the “new” naming done by SAPUI5. By altering the above selector slightly, we can make it look for all “div” elements containing the string “chart”:
Note that I am also passing our JSON “myData” to the function – this is my JSON model as derived from the original OData service. The main thing here is that the selector now works also in an SAPUI5 XML content.
More info on JQuery selectors and how to build them can be found here:
Data provisioning – stuffing our charts with zombies
Local data relate to locally defined JSON models. This also amounts to hard-coding for mockup scenarios, and is also not very interesting for “real” applications.
Our example works with remote data – provided by a Gateway OData service. For use in the Kendo controls, the data will have to be in JSON format. Because of this “limitation”, we translated the data to JSON format when reading the OData service.
One issue with this way of providing JSON data from an OData source is that the Kendo code has issues with “complex” data models, such as the ones provided by OData-to-JSON conversion. If we simply declare our chart by copying and pasting the generic Kendo sample code, like most exampoles found on the site (related to JSON models) we may run into problems.
Running “standard” Kendo chart code will easily result in the following error:
This is due to the relative complexity of our JSON data:
Note the “results” element at the top of the JSON structure.
In order to resolve this, we need to declare a “schema” in our dataSource parameter for the chart:
Here, we declare the header node = “results” – this is all that is needed to enable Kendo to correctly traverse the JSON model.
A Kendo forum post regarding this issue can be found here:
The result of our efforts:
As can be seen, Las Vegas is the place to steer clear of, regarding zombies.
Changing the chart type: Donut chart
With the above framework in place, it’s fairly easy to create new chart types. We simply alter the createChart function to specify a different type:
(Note that some chart types are suitable for specific types of data – depending on the complexity of the data).
I hope this provided some ideas of what is possible; the concepts should be useful also for other 3rd party UI libraries.
These examples were developed using Web IDE on a HANA Cloud platform, with data pulled from a Gateway system.