Skip to Content
Author's profile photo Jeroen Thoden van Velzen

Custom SAPUI5 Visualization Controls with D3.js

Over the last couple of months I have been playing with D3.js, the JavaScript visualization library that allows you to programmatically create SVG visualizations on the basis of a data set. I love how this allows me to think up how to visualize a particular dataset without any constraints of the capabilities of any charts and graph package included in whatever tool you would otherwise have used. I have since built out custom extensions in Lumira using D3.js, and when I started looking at SAPUI5, one of the first things I wanted to do was create my own D3.js SAPUI5 custom controls.

There have been other articles on including D3.js in SAPUI5 (most notably here and here), but they used an HTML template, rather than include it in a custom control that could be used largely like any other SAPUI5 control. Well, after a bit of puzzling and some help from a colleague who had built custom controls based on other SAPUI5 controls for a different project, I managed to figure it out, and through this blog, I hope to help you create your own.

This is one of the controls I created. You see it here included in a page, embedded within a <Panel> tag. It receives a data set of target, currently booked revenue and a forecast, and then shows the percentage of booked revenue and forecast against the target. We will focus here largely on the SAPUI5 custom control parts rather than the D3.js code, but the control is available for download at the bottom of this blog.

/wp-content/uploads/2014/07/d3_custom_control_500377.png

Building the Chart Control

Let’s create our custom control: create a new folder called “controls” inside the WebContent folder of your SAPUI5 application, and create a new JavaScript file. We’ll use the attached D3ChartTemplate.js as an example. In your own controls you should change the class names (and filename) to something a bit more descriptive so you know which is which, and typically you’d call your JavaScript file the same as the control (i.e. BarChart.js would contain BarChart and BarChartItem classes).

We start with a requirement to load the built-in third party D3 library and a declaration of the chart itself:

jQuery.sap.require(“sap/ui/thirdparty/d3”);

jQuery.sap.declare(“sap.jaysdk.Chart”);

Then, we need to define our ChartItem. This is used to map between what the chart expects and the dataset you are trying to visualize. You’ll see this once we get to instantiating the chart.

sap.ui.core.Element.extend(“sap.jaysdk.ChartItem”, { metadata : {

       properties : {

              “region” : {type : “string”, group : “Misc”, defaultValue : null},

              “budget” : {type : “string”, group : “Misc”, defaultValue : null},

              “bw” : {type : “string”, group : “Misc”, defaultValue : null},

              “forecast” : {type : “string”, group : “Misc”, defaultValue : null

       }

}});


We then set up the definition of the Chart itself:

sap.ui.core.Control.extend(“sap.jaysdk.Chart”, {

       metadata : {

              properties: {

                     “title”: {type : “string”, group : “Misc”, defaultValue : “Chart Title”}

              },

              aggregations : {

                     “items” : { type: “sap.jaysdk.ChartItem”, multiple : true, singularName : “item”}

              }

              ,

              defaultAggregation : “items”,

              events: {

                     “onPress” : {},

                     “onChange”:{}       

              }                   

       },

       …

}

You see here the ChartItem referenced. Once data is passed in, these will become our “items”.

We need to split the setup of the chart separately from the D3.js code, since we need to create the placeholder first, while the D3.js code will only run after rendering the HTML through the Chart’s onAfterRendering() function. So, let’s create the chart:

createChart : function() {

              /*

         * Called from renderer

         */

        console.log(“sap.jaysdk.Chart.createChart()”);

              var oChartLayout = new sap.m.VBox({alignItems:sap.m.FlexAlignItems.Center,justifyContent:sap.m.FlexJustifyContent.Center});

              var oChartFlexBox = new sap.m.FlexBox({height:“180px”,alignItems:sap.m.FlexAlignItems.Center});

              /* ATTENTION: Important

         * This is where the magic happens: we need a handle for our SVG to attach to. We can get this using .getIdForLabel()

         * Check this in the ‘Elements’ section of the Chrome Devtools:

         * By creating the layout and the Flexbox, we create elements specific for this control, and SAPUI5 takes care of

         * ID naming. With this ID, we can append an SVG tag inside the FlexBox

         */

              this.sParentId=oChartFlexBox.getIdForLabel();

        oChartLayout.addItem(oChartFlexBox);

           

              return oChartLayout;

    },

We create a VBox and place a FlexBox inside of it. Then, as the comments already suggest, we get the magic. Rather than using a <div> tag or <span> tag that we write deliberately in an HTML file, we’re going to leverage the identifier of the FlexBox to attach our SVG to. This is what it looks like in the Chrome DevTools “Elements” section:

/wp-content/uploads/2014/07/div_id_500399.png


The “__box2” id is what we will use and is stored in this.sParentId.

We have a pretty standard renderer function, with the only difference that we call the createChart function.

renderer : function(oRm, oControl) {

              var layout = oControl.createChart();

        oRm.write(“<div”);

        oRm.writeControlData(layout); // writes the Control ID and enables event handling – important!

        oRm.writeClasses(); // there is no class to write, but this enables

              // support for ColorBoxContainer.addStyleClass(…)

           

        oRm.write(“>”);

        oRm.renderControl(layout);

        oRm.addClass(‘verticalAlignment’);

        oRm.write(“</div>”);

    

   },


Finally, the Chart is completed in the onAfterRendering() function:

onAfterRendering: function(){

        console.log(“sap.jaysdk.Chart.onAfterRendering()”);

        console.log(this.sParentId);

              var cItems = this.getItems();

              var data = [];

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

                     var oEntry = {};

                     for (var j in cItems[i].mProperties) {

                oEntry[j]=cItems[i].mProperties[j];

            }                                

            data.push(oEntry);

        }

              //console.log(“Data:”);

              //console.log(data);

           

              /*

         * ATTENTION: See .createChart()

         * Here we’re picking up a handle to the “parent” FlexBox with the ID we got in .createChart()

         * Now simply .append SVG elements as desired

         * EVERYTHING BELOW THIS IS PURE D3.js

         */

           

              var vis = d3.select(“#” + this.sParentId);

           

              //Your D3.js code HERE

                     

       }

We get the “items” that were passed in containing our data, and read it into the data array. Once that has run, you have the dataset from your model in the chart and you are ready to build out your SVG. We can now attach to the <div> tag with the id we retrieved before using d3.select. After that, it is just standard D3.js code!

Using the Chart control

We can now try to use the chart in our SAPUI5 pages. We start with creating a container inside the Xxx.view.xml file:

<Panel>

<headerToolbar>

              <Toolbar>

                     <Label text=“YTD Booked/Won and Forecast to Budget (Percentage)” />

              </Toolbar>

       </headerToolbar>

       <FlexBox id=“ChartHolder” alignItems=“Start” justifyContent=“Center”>

</FlexBox>

</Panel>

This creates the location that we will place our chart in. Now we need to add the chart to our Xxx.controller.js. We need start with declaring the Chart and the ChartItem. The resource path should be the path to your custom control relative to index.html and its name without the js extension. Notice that since the ChartItem is embedded in the controls/Chart.js file, its module path is controls/Chart. Again, for your own controls, use the same convention, but obviously a more descriptive name for your custom chart.


jQuery.sap.registerModulePath(“sap.jaysdk.Chart”, “controls/Chart”);

jQuery.sap.require(“sap.jaysdk.Chart”);

jQuery.sap.registerModulePath(“sap.jaysdk.ChartItem”, “controls/Chart”);

jQuery.sap.require(“sap.jaysdk.ChartItem”);

Next, we instantiate our chart, inside the onBeforeRendering() function (or a separate function call from within that event function). We find the ChartHolder FlexBox, create a ChartItem that maps the fields from the data in your model to the chart, and create a new chart (here with a path included). We then get a handle on the model and set the model to the chart. Finally, we add the chart to the FlexBox container.

var oChartHolder = this.byId(“ChartHolder”);

var oChartItem = new sap.jaysdk.ChartItem({region:“{region}”, budget:“{budget}”, bw:“{bw_ytd}”, forecast:“{forecast}”});

/* new  chart */

var oChart = new sap.jaysdk.Chart({

       items: {path : “/regions”, template : oChartItem}

});

           

var oModel = sap.ui.getCore().getModel(“chart”);

oChart.setModel(oModel);

oChartHolder.addItem(oChart);

And that’s it! Your chart should now be visible in your application, and can be embedded like any other control.

Attached below you’ll find the D3ChartTemplate as well as the PerformanceToTargetComparison chart of which a screenshot is shown at the top of this blog. I have also included a JSON file with the sample data.

SAPUI5 is an excellent framework to quickly develop business applications, and using the techniques described here, you can now add any fancy visualization you would like. Happy hacking!

Assigned Tags

      14 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Zhunzhun Duan
      Zhunzhun Duan

      In the view controller that adds the Custom D3Control, I suggest to use onAfterRendering() hook.

      Because when I use the onBeforeRendering() hook in the view controller to add the Custom D3Chart, I got two charts.

      When I turn to use onAfterRendering() hook to add it, the issue solved - only one chart.

      I guess that's because I test the view that uses the Custom D3Chart as the first screen of my simple HTML app, SAPUI5 fires firstly the view's onInit() hook then fires the view's onBeforeRendering() hook, so I got twice onBeforeRendering() and two Custom D3Chart.

      Author's profile photo Jeroen Thoden van Velzen
      Jeroen Thoden van Velzen
      Blog Post Author

      Hi Zhunzhun,

      Thanks for that. I think you're right, that it depends a bit on the structure of your application when and how the events fire and where to put the initialization. I didn't see this problem with my own charts using this approach, but I did see it in a previous attempt where I was passing in different data to the same page, and at each new access I would get a new chart added.

      I actually got around that by simply calling .selectAll("svg").remove(); before adding any new content.

      I deliberately put console.log messages at the start of my functions to show which functions are called. If onAfterRendering() fixes it, let's just use that one, then.

      Thanks again!

      Author's profile photo Zhunzhun Duan
      Zhunzhun Duan

      Hi Jay,

      Thanks for your reply, it make me more clear.

      How about put the "add Custom D3Chart to oChartHolder " code in the onInit() hook and "reset the data binding" code in onBeforeShow() hook?

      As "add Custom D3Chart to oChartHolder " is one-time initialization and "a setting that are not possible in the XMLView, it can be set in the controller's onInit() hook instead". (quoted by Andreas Kunz)

      But "reset the data binding" code can reuse the Custom D3Chart setted in onInit() hooks for multiple times, then we use the onBeforeRendering() hook to reset the model before rerendering.

      _______________________________

      some more question here, the Custom D3Chart seems not re-rendering when I reset the Data Bind in Google Chrome console:

      sap.ui.getCore().byId("__xmlview0--ChartHolder").setModel(new sap.ui.model.json.JSONModel({}))


      or


      var data = sap.ui.getCore().byId("__xmlview0--ChartHolder").getModel().getData();

      data.regions[0].region = "China";

      sap.ui.getCore().byId("__xmlview0--ChartHolder").getModel().setData(data)


      Is there something additional to do in Costom D3Chart?



      Thanks,

      Antoine

      Author's profile photo Jeroen Thoden van Velzen
      Jeroen Thoden van Velzen
      Blog Post Author

      Thanks, Zhunzhun. Great stuff.

      As far as Antoine's question goes: I would have assumed you'd set the model again, rather than just set new data to the model.

      But I've struggled with models, data and updates myself, so not sure what is going on. The SVG gets built out in onAfterRendering() so perhaps doing it this way doesn't re-render the control? Maybe that gets triggered by setModel()?

      Author's profile photo Zhunzhun Duan
      Zhunzhun Duan

      Hi Jay,

      Thanks for your kind reply.

      `Antoine` is a French Alias Name of me. 😆

      No, I don't trigger the reset data binding in any hooks here. I trigger it  inside Chrome CONSOLE. Normally this way works on Table, Buttons...

      I used the setModel() : sap.ui.getCore().byId("__xmlview0--ChartHolder").setModel(new sap.ui.model.json.JSONModel({}))

      Nothing happens.

      Yes, we really need to know how SAPUI5 deal with re-rendering mechanism and how data-binding trigger re-rendering.

      Best Regards,

      Zhunzhun

      Author's profile photo Jeroen Thoden van Velzen
      Jeroen Thoden van Velzen
      Blog Post Author

      Aah, I see. 😉

      Yeah, a bit better documentation on view and component life cycle and exactly when what events run would be great help. It can be a bit of a puzzle now, with events firing more often than you expect, and sometimes less than you expect (returning to a page that has already been rendered before, for instance).

      Author's profile photo Jeroen Thoden van Velzen
      Jeroen Thoden van Velzen
      Blog Post Author

      In order to see these custom controls in action, you may want to check out the demo code here: https://github.com/jay-sdk/SAPUI5-reporting-app

      This may specifically help in dealing with issues of updates to the same page/view from a different selection. (specifically the "GrowthRegion" view, where the container is emptied of content before adding the updated SVG in). Maybe not the most elegant approach, but it works.

      Author's profile photo Former Member
      Former Member

      Hi,

      we experiment with your example and have a  question. When we instantiate the graph in the onBeforeRendering method, an OData call is triggered to collect the graph data and bind the data to the graph.

      In onAfterRendering of Chart.js we don't have the items yet, because the OData request takes a couple ms to be finished. Hence, this.getItems() returns an empty array.

      Any idea how to defer the process without using setTimeOut? I see no possibility to use callbacks at the moment, because the code is spread across two files.

      Kind regards,

      Michael

      Author's profile photo Jeroen Thoden van Velzen
      Jeroen Thoden van Velzen
      Blog Post Author

      Hi Michael,

      I am not the best person to answer, as I struggle with this myself at times, but will try to steer a colleague your way here on this question.

      Author's profile photo Former Member
      Former Member

      Hi Jay,

      thanks for your great blog, which jumpstarted me on this topic. My questions:

      1. Why do you use the VBox and the FlexBox? Are these for styling purposes only (horizontal and vertical alignment)? In that case I suppose it's overkill to employ controls just for that purpose, it may be more efficient to just assign appropriate CSS styles/classes.
      2. Is it possible to get D3 injected via sap.ui.define? I tried

        sap.ui.define(["sap/ui/thirdparty/d3"], function(oD3) { ...

        but then oD3 is undefined.

      Here's how I did it without VBox/FlexBox:

      renderer : function(oRm, oControl) {

        var sId = oControl.getId();

        oRm.write("<div");              // Control - DIV

        oRm.writeControlData(oControl); // writes the Control ID and enables event handling - important!

        oRm.writeClasses();

        oRm.write('><div id="' + sId + '-svgContainer"></div>');

        oRm.write("</div>");          // end Control - DIV

      },

      onAfterRendering: function(){

        var sDomID, oVis;

        sDomID = this.getId();

        oVis   = d3.select("#" + sDomID + "-svgContainer").node();

        //Your D3.js code HERE

      }

      Author's profile photo Former Member
      Former Member

      I think creating a custom control just to embed a chart into UI5 application is too much overhead, I've written a blog about another approach, which I think is much easier and superior. If you're interested, check it out.

      Author's profile photo Priya Jha
      Priya Jha

      Hi Jay,

      Thanks for the blog. I have followed the blog and created the d3 chart into a custom ui5 control. In the console i am able to see the instance of the custom control but i am not able to see my control.

      However, I see the div tags written in my pannel.

      //Importing QR code for reonboarding
      
      jQuery.sap.declare("hc.pe.managepatients.controls.D3Chart");
      jQuery.sap.require("sap/ui/thirdparty/d3");
      
      sap.ui.core.Element.extend("hc.pe.managepatients.controls.D3ChartItem", {
      	metadata: {
      
      		properties: {
      			"date": {
      				type: "date",
      				group: "Misc",
      				defaultValue: null
      			},
      			"time": {
      				type: "date",
      				group: "Misc",
      				defaultValue: null
      			},
      			"legendtext": {
      				type: "string",
      				group: "Misc",
      				defaultValue: null
      			},
      			"forecast": {
      				type: "string",
      				group: "Misc",
      				defaultValue: null
      			}
      		}
      	}
      });
      sap.ui.core.Control.extend("hc.pe.managepatients.controls.D3Chart", {
      
      	metadata: {
      		properties: {
      			"Chart Title": {
      				type: "string",
      				group: "Misc",
      				defaultValue: "Chart Title"
      			}
      		},
      		aggregations: {
      			"items": {
      				type: "hc.pe.managepatients.controls.D3ChartItem",
      				multiple: true,
      				singularName: "item"
      			}
      		},
      		defaultAggregation: "items",
      		events: {
      			"onPress": {},
      			"onChange": {}
      		}
      	},
      
      	init: function() {
      		console.log("hc.pe.managepatients.controls.D3Chart");
      		this.sParentId = "";
      	},
      
      	createChart: function() {
      		/*
      		 * Called from renderer
      		 */
      		console.log("hc.pe.managepatients.controls.D3Chart.createChart()");
      		var oChartLayout = new sap.m.VBox({
      			alignItems: sap.m.FlexAlignItems.Center,
      			justifyContent: sap.m.FlexJustifyContent.Center
      		});
      		var oChartFlexBox = new sap.m.FlexBox({
      			//	height: '180 em',
      			alignItems: sap.m.FlexAlignItems.Center
      		});
      		/* ATTENTION: Important
      		 * This is where the magic happens: we need a handle for our SVG to attach to. We can get this using .getIdForLabel()
      		 * Check this in the 'Elements' section of the Chrome Devtools:
      		 * By creating the layout and the Flexbox, we create elements specific for this control, and SAPUI5 takes care of
      		 * ID naming. With this ID, we can append an SVG tag inside the FlexBox
      		 */
      		this.sParentId = oChartFlexBox.getIdForLabel();
      		oChartLayout.addItem(oChartFlexBox);
      
      		return oChartLayout;
      	},
      	cValue: function(d) {
      		return d.time;
      	},
      	textValue: function(d) {
      		var time = parseInt(d.toString().substr(16, 2));
      		if (time > 8 && time < 12) {
      			return "Breakfast";
      		} else if (time > 12 && time < 17) {
      			return "Lunch";
      		}
      		if (time > 18 && time < 23) {
      			return "Dinner";
      		}
      	},
      	renderer: function(oRm, oControl) {
      		var layout = oControl.createChart();
      		oRm.write(" < div");
      		oRm.writeControlData(layout); // writes the Control ID and enables event handling – important!
      			oRm.writeClasses(); // there is no class to write, but this enables
      		// support for ColorBoxContainer.addStyleClass(…)
      
      		oRm.write(" > ");
      		oRm.renderControl(layout);
      		//oRm.addClass('verticalAlignment');
      		oRm.write(" < /div>");
      
      	},
      	onAfterRendering: function() {
      
      		var width = 1660;
      		var height = 700;
      		var padding = 100;
      		var margin = {
      				top: 20,
      				right: 20,
      				bottom: 30,
      				left: 40
      			},
      
      			width = 1260 - margin.left - margin.right,
      			height = 500 - margin.top - margin.bottom;
      
      		console.log("hc.pe.managepatients.controls.D3Chart.onAfterRendering()");
      		console.log(this.sParentId);
      		var cItems = this.getItems();
      		var data = [];
      		for (var i = 0; i < cItems.length; i++) {
      			var oEntry = {};
      			for (var j in cItems[i].mProperties) {
      				oEntry[j] = cItems[i].mProperties[j];
      			}
      			data.push(oEntry);
      		}
      		//console.log("Data:");
      		//console.log(data);
      
      		/*
      		 * ATTENTION: See .createChart()
      		 * Here we're picking up a handle to the "parent" FlexBox with the ID we got in .createChart()
      		 * Now simply .append SVG elements as desired
      		 * EVERYTHING BELOW THIS IS PURE D3.js
      		 */
      		var margin = {
      			top: 20,
      			right: 20,
      			bottom: 30,
      			left: 40
      		};
      		var that = this;
      		var vis = d3.select("#" + this.sParentId);
      		vis.append("svg:svg")
      			.attr("width", width)
      			.attr("height", height);
      		// add the graph canvas to the body of the webpage
      		vis = d3.select("body").append("svg")
      			.attr("width", width + margin.left + margin.right)
      			.attr("height", height + margin.top + margin.bottom)
      			.append("g")
      			.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
      		// define the y scale  (vertical)
      
      		var mindate = new Date(2012, 0, 1),
      			maxdate = new Date(2012, 0, 31);
      
      		var start_of_day = new Date();
      		start_of_day.setHours(0, 0, 0, 0);
      		var end_of_day = new Date();
      		end_of_day.setHours(23, 59, 59, 999);
      
      		var yScale = d3.time.scale()
      			.domain([start_of_day, end_of_day])
      			.nice(d3.time.day) // values between 0 and 100
      			.range([height - padding, padding]); // map these to the chart height, less padding.  
      		//REMEMBER: y axis range has the bigger number first because the y value of zero is at the top of chart and increases as you go down.
      
      		// define the x scale (horizontal)
      		var mindate = new Date(2016, 11, 1),
      			maxdate = new Date();
      
      		var xScale = d3.time.scale()
      			.domain([mindate, maxdate]) // values between for month of january
      			.range([padding, width - padding * 2]); // map these the the chart width = total width minus padding at both sides
      
      		// define the y axis
      
      		var yValue = function(d) {
      			return d.time;
      		}; // data -> value
      		var yMap = function(d) {
      			return yScale(yValue(d));
      		};
      		var yAxis = d3.svg.axis()
      			.orient("left")
      			.scale(yScale).ticks(24).tickFormat(d3.time.format("%H:%M"));
      
      		// define the x axis
      		// setup x 
      		var xValue = function(d) {
      			return d.date;
      		}; // data -> value
      		// value -> display
      		var xMap = function(d) {
      			return xScale(xValue(d));
      		};
      		var xAxis = d3.svg.axis()
      			.orient("bottom")
      			.scale(xScale).tickFormat(d3.time.format("%Y-%m-%d"));
      
      		// draw y axis with labels and move in from the size by the amountf of padding
      		vis.append("g")
      			.attr("transform", "translate(" + padding + ",0)")
      			.style({
      				'stroke': 'Black',
      				'fill': 'none',
      				'stroke-width': '1px'
      			})
      
      		.call(yAxis);
      
      		// draw x axis with labels and move to the bottom of the chart area
      		vis.append("g")
      			.attr("class", "xaxis") // give it a class so it can be used to select only xaxis labels  below
      			// .attr("transform", "translate(0," + (height - padding) + ")")
      			.attr("transform", "translate(0," + (height - padding) + ")")
      			.style({
      				'stroke': 'Black',
      				'fill': 'none',
      				'stroke-width': '1px'
      			})
      
      		.call(xAxis);
      
      		// draw dots
      
      		vis.selectAll(".dot")
      			.data(data)
      			.enter().append("circle")
      			.attr("class", "dot")
      			.attr("r", 3.5)
      			.attr("cx", xMap)
      			.attr("cy", yMap)
      			.style("fill", function(d) {
      				var time = parseInt(d.time.toString().substr(16, 2));
      
      				return color(that.cValue(d));
      			});
      		/*		.on("mouseover", function(d) {
      					tooltip.transition()
      						.duration(200)
      						.style("opacity", .9);
      					tooltip.html(d["Cereal Name"] + "<br/> (" + xValue(d) +
      							", " + yValue(d) + ")")
      						.style("left", (d3.event.pageX + 5) + "px")
      						.style("top", (d3.event.pageY - 28) + "px");
      				})
      				.on("mouseout", function(d) {
      					tooltip.transition()
      						.duration(500)
      						.style("opacity", 0);
      				});*/
      
      		// now rotate text on x axis
      		// solution based on idea here: https://groups.google.com/forum/?fromgroups#!topic/d3-js/heOBPQF3sAY
      		// first move the text left so no longer centered on the tick
      		// then rotate up to get 45 degrees.
      
      		var color = d3.scale.category10();
      
      		var data = [{
      				"date": "30-Dec-16",
      				"Text": "Lunch",
      				"time": "Mon Dec 30 2016 16:29:23 GMT+0530 (India Standard Time)",
      				"close": "30"
      			}, {
      				"date": "30-Dec-16",
      				"Text": "Breakfast",
      				"time": "Mon Jan 27 2017 11:29:23 GMT+0530 (India Standard Time)",
      				"close": "20"
      			},
      
      			{
      				"date": "30-Dec-16",
      				"Text": "Dinner",
      				"time": "Mon Feb 10 2017 21:29:23 GMT+0530 (India Standard Time)",
      				"close": "10"
      			}, {
      				"date": "01-Jan-17",
      				"Text": "Lunch",
      				"time": "Mon Dec 30 2016 16:29:23 GMT+0530 (India Standard Time)",
      				"close": "30"
      			}, {
      				"date": "01-Jan-17",
      				"Text": "Breakfast",
      				"time": "Mon Jan 27 2017 11:29:23 GMT+0530 (India Standard Time)",
      				"close": "20"
      			},
      
      			{
      				"date": "01-Jan-17",
      				"Text": "Dinner",
      				"time": "Mon Feb 10 2017 21:29:23 GMT+0530 (India Standard Time)",
      				"close": "10"
      			}
      		];
      		var dateformat = d3.time.format("%H:%M").parse;
      		var parseDate = d3.time.format("%d-%b-%y").parse;
      		data.forEach(function(d) {
      			d.date = parseDate(d.date);
      			//d.time=formattedDateTime(d.time);
      			//d3.time.format('%H %M')(new Date(d.time));
      			var today = new Date();
      			var time = new Date(d.time);
      			today.setHours(time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());
      			d.time = today;
      		});
      
      		vis.selectAll(".xaxis text") // select all the text elements for the xaxis
      			.attr("transform", function(d) {
      				return "translate(" + this.getBBox().height + "," + this.getBBox().height + ")";
      			});
      		// draw legend
      		var legend = vis.selectAll(".legend")
      			.data(color.domain())
      			.enter().append("g")
      			.attr("class", "legend")
      			.attr("transform", function(d, i) {
      				return "translate(0," + i * 20 + ")";
      			});
      
      		// draw legend colored rectangles
      		legend.append("rect")
      			.attr("x", width - 18)
      			.attr("width", 18)
      			.attr("height", 18)
      			.style("fill", color);
      
      		// draw legend text
      		legend.append("text")
      			.attr("x", width - 24)
      			.attr("y", 9)
      			.attr("dy", ".35em")
      			.style("text-anchor", "end")
      			.text(function(d) {
      				return that.textValue(d);
      			});
      
      		
      
      	}
      });
      
      
      
      //This is the OnBeforeRendering function from where i call the chart
      	onAfterRendering: function() {
      						var oModel = new sap.ui.model.json.JSONModel();
      						var data = [{
      								"date": "30-Dec-16",
      								"Text": "Lunch",
      								"time": "Mon Dec 30 2016 16:29:23 GMT+0530 (India Standard Time)",
      								"forecast": "30"
      							}, {
      								"date": "30-Dec-16",
      								"Text": "Breakfast",
      								"time": "Mon Jan 27 2017 11:29:23 GMT+0530 (India Standard Time)",
      								"forecast": "20"
      							},
      
      							{
      								"date": "30-Dec-16",
      								"Text": "Dinner",
      								"time": "Mon Feb 10 2017 21:29:23 GMT+0530 (India Standard Time)",
      								"forecast": "10"
      							}, {
      								"date": "01-Jan-17",
      								"Text": "Lunch",
      								"time": "Mon Dec 30 2016 16:29:23 GMT+0530 (India Standard Time)",
      								"forecast": "30"
      							}, {
      								"date": "01-Jan-17",
      								"Text": "Breakfast",
      								"time": "Mon Jan 27 2017 11:29:23 GMT+0530 (India Standard Time)",
      								"forecast": "20"
      							},
      
      							{
      								"date": "01-Jan-17",
      								"Text": "Dinner",
      								"time": "Mon Feb 10 2017 21:29:23 GMT+0530 (India Standard Time)",
      								"forecast": "10"
      							}
      						];
      						oModel.setData(data);
      
      						var oChartHolder = this.byId("ChartHolder");
      						var oChartItem = new hc.pe.managepatients.controls.D3ChartItem({
      							date: "{date}",
      							time: "{time}",
      							legendtext: "{Text}",
      							forecast: "{forecast}"
      						});
      						/* new  chart */
      						var oChart = new hc.pe.managepatients.controls.D3Chart({
      								items: {
      									path: " /", template : oChartItem}
      								});
      
      							//var oModel = sap.ui.getCore().getModel("chart");
      							oChart.setModel(oModel);
      
      							oChartHolder.addItem(oChart);
      						}
      					});
      

       

       

      Author's profile photo Priya Jha
      Priya Jha

      Any help will be highly appreciated

      Author's profile photo Former Member
      Former Member

      Hi,

      I could not find the attachement, can some please help me with that?

      TIA

      Meeti