Work with external js libraries in DataFlex
I have been assigned a project where I need to show some graphs inside of a DataFlex application. So I needed to integrate a graph library into the DataFlex project. In this post and the video above I highlight the key points in order to get a complete integration to work.
Include the library
External librarys come with some premade source files that you need to load in your html header section of Index.html. Then you have another part where you use the functionallity of the library in order to show something on the screen. This code I have put in a separate file called graph.js. But you can place it in the Index.html as well if you prefere that.
Sending the data
We can use any data we manage in the system as long as we compos it into a string that matches the data the library expects. And in order to add a placeholder for the graph I created an WebHtmlBox called oGraph_box and with a separate procedure filled it with html containing the data and the elements I needed to render the graph.
Move "[['Mushrooms', 15],['Onions', 1],['Olives', 7],['Zucchini', 1],['Pepperoni', 2]]" to sData
Move (sHtml + '') to sHtml
Move (sHtml + '') to sHtml
Send UpdateHTML to oGraph_box sHtml
In order to recieve the data in the javascript I need to read the value of graph_data and turn that string into an object. This is how I managed that:
// Get the string from the element graph_data
var dataObj = document.getElementById('graph_data');
// Change all the single quotes (') to double quotes (") in order for it to be valid JSON
dataObj.value = dataObj.value.replace(/'/g, '"');
// Add additional structure to the string in order to make it a valid JSON string and then use JSON.pars to turn it into a js object
var graphData = JSON.parse('{"data": ' + dataObj.value + "}");
// Now I can feed the graph enging with the data like this
data.addRows(graphData.data);
But before any of this occurs I need to execute it from the serverside. And I do that by containing all of the javascript code in a function I call "runGraph"
var runGraph = function() {
// your js code
};
And then I call that from the server by activating the pbServerOnShow property and telling it to call runGraph with the psClientOnShow property.
Set pbServerOnShow to True
Set psClientOnShow to "runGraph"
Now the code will generate a graph on the page.
Handle events
Now I would like to be able to send data back to the server when I interract with the js library. And in order to do that we need to start to add a procedure that can recieve the call from the view. Inside of the oGraph_box I added the following:
// On order for the object to allow events from the client we need to activate the pbServerOnClick for this object
Set pbServerOnClick to True
Procedure OnClick String sId String sParam
If (Trim(sId) <> "") Begin
// Here you can do what ever you like with the data you get back
Showln ("You pressed " + sId)
End
End_Procedure
In order to call this procedure placed in oWebApp -> oGraph -> oWebMainPanel -> oGraph_box you need to use the following call:
// call fire on the element and then say what procedure to call and include an array with elements
oWebApp.oGraph.oWebMainPanel.oGraph_box.fire('OnClick', [data.getValue(selectedItem.row, 0)]);
// You may also do a set, in order to change a property of an element
oWebApp.oGraph.oWebMainPanel.oGraph_box.set("pbRender", false);
If you enjoy this video then don't forget to go into the channel on youtube and subscribe or add your mail to my newsletter. You may also want to see all episodes of Discovering DataFlex available on youtube.
UPDATE...
There are some issues with this implementation and I will try to explain them here:
There is a race condition between the rendering of the data and the execution of the graph rendering javascript. I had to use a function like the one below to delay the execution of the graph rendering javasript in order to avoid the race condition.
var execPortal = function() {
//runPortal();
var jsonElem = document.getElementById('json_data');
//console.log(jsonElem);
if (jsonElem !== null) {
//console.log('activate');
runPortal();
} else {
setTimeout(execPortal, 10);
}
};
Then when you re-enter the page you will have another problem with jsonElem not being null so you need to remove it after you have read the data like below.
var jsonElem = document.getElementById('json_data');
var jsonData = JSON.parse(jsonElem.innerHTML);
jsonElem.remove();
Hope this solves your issue
- dataflex, javascript library, integration, software