Basic example of Google Charts with DataFlex WebApp: Difference between revisions
(11 intermediate revisions by 3 users not shown) | |||
Line 3: | Line 3: | ||
Below we will create a DataFlex wrapper component for the Google Charts component. | Below we will create a DataFlex wrapper component for the Google Charts component. | ||
A wrapper consists of multiple parts working together, so that you can use the control directly from your DataFlex web application. | A wrapper consists of multiple parts working together, so that you can use the control directly from your DataFlex web application. The first two elements are the client-side JavaScript part (actually a JavaScript pseudo-class) and the server-side DataFlex class, which together make up the new component. | ||
=== The | === The JavaScript part === | ||
Create a new folder GoogleCharts in your AppHtml folder and put the following in the file Charts.js | Create a new folder GoogleCharts in your AppHtml folder and put the following in the file Charts.js | ||
Line 200: | Line 200: | ||
=== An example web object === | === An example web object === | ||
Now that we have our component, we need to deploy it, so here is a sample view using it: | |||
<source lang="dataflex"> | <source lang="dataflex"> | ||
Line 290: | Line 292: | ||
<!-- Initialization of the WebApp --> | <!-- Initialization of the WebApp --> | ||
...</source> | ...</source> | ||
=== Screenshots and example workspace === | |||
[[File:GoogleChartsDemo-PieChart.png|200px|Pie Chart Demo]] | |||
[[File:GoogleChartsDemo-BarChart.png|200px|Bar Chart Demo]] | |||
[[File:GoogleChartsDemo-AreaChart.png|200px|Area Chart Demo]] | |||
You can download a completely functional DataFlex 19.1 Workspace down here, unzip, register in DataFlex 19.1, let the Studio create the javascript engine folders and run: | |||
[[File:GoogleChartsDemo-20200326.zip]] | |||
===Addendum...=== | |||
Never one to leave well enough alone, I have been playing further... | |||
In the JavaScript, I extended the "switch" statement in the chartDef function as follows: | |||
<source lang=javascript> | |||
switch (obj.psChartType) { | |||
case "PieChart": | |||
chart = new google.visualization.PieChart(obj._eControl); | |||
break; | |||
case "BarChart": | |||
chart = new google.visualization.BarChart(obj._eControl); | |||
break; | |||
case "AreaChart": | |||
chart = new google.visualization.AreaChart(obj._eControl); | |||
break; | |||
case "ColChart": | |||
chart = new google.visualization.ColumnChart(obj._eControl); | |||
break; | |||
case "LineChart": | |||
chart = new google.visualization.LineChart(obj._eControl); | |||
break; | |||
case "ScatterChart": | |||
chart = new google.visualization.ScatterChart(obj._eControl); | |||
break; | |||
default: | |||
chart = new google.visualization.PieChart(obj._eControl); | |||
} | |||
</source> | |||
In order to include more chart types. | |||
In the DataFlex class, all that changed was the definition of some new constants: | |||
<source lang=dataflex> | |||
Define C_chartTypePie for "PieChart" | |||
Define C_chartTypeBar for "BarChart" | |||
Define C_chartTypeArea for "AreaChart" | |||
Define C_chartTypeScat for "ScatterChart" | |||
Define C_chartTypeLine for "LineChart" | |||
Define C_chartTypeCol for "ColChart" | |||
// etc... | |||
</source> | |||
Then in the sample view (Chart.wo), I got rid of the button and just had the radio controls themselves set things off: | |||
<source lang=dataflex> | |||
Use cWebView.pkg | |||
Use cWebPanel.pkg | |||
Use cWebForm.pkg | |||
Use cWebButton.pkg | |||
Use cWebChart.pkg | |||
Use cWebRadio.pkg | |||
Object oChart is a cWebView | |||
Set piWidth to 1000 | |||
Set psCaption to "Chart" | |||
Delegate Set phoDefaultView to Self | |||
Object oWebMainPanel is a cWebPanel | |||
Set piColumnCount to 12 | |||
Object oPie is a cWebRadio | |||
Set piColumnSpan to 2 | |||
Set psCaption to "Pie Chart" | |||
Set psRadioValue to C_chartTypePie | |||
Set pbServerOnChange to True | |||
Procedure OnChange | |||
Send DrawChart | |||
End_Procedure | |||
Procedure OnLoad | |||
Send DrawChart | |||
End_Procedure | |||
End_Object | |||
Object oBar is a cWebRadio | |||
Set piColumnSpan to 2 | |||
Set piColumnIndex to 2 | |||
Set psCaption to "Bar Chart" | |||
Set psRadioValue to C_chartTypeBar | |||
End_Object | |||
Object oArea is a cWebRadio | |||
Set piColumnSpan to 2 | |||
Set piColumnIndex to 4 | |||
Set psCaption to "Area Chart" | |||
Set psRadioValue to C_chartTypeArea | |||
End_Object | |||
Object oColumn is a cWebRadio | |||
Set piColumnSpan to 2 | |||
Set piColumnIndex to 6 | |||
Set psCaption to "Column Chart" | |||
Set psRadioValue to C_chartTypeCol | |||
End_Object | |||
Object oLine is a cWebRadio | |||
Set piColumnSpan to 2 | |||
Set piColumnIndex to 8 | |||
Set psCaption to "Line Chart" | |||
Set psRadioValue to C_chartTypeLine | |||
End_Object | |||
Object oScatter is a cWebRadio | |||
Set piColumnSpan to 2 | |||
Set piColumnIndex to 10 | |||
Set psCaption to "Scatter Chart" | |||
Set psRadioValue to C_chartTypeScat | |||
End_Object | |||
Procedure DrawChart | |||
String sType | |||
Send Initalize of oChart | |||
WebGet psValue of oPie to sType | |||
WebSet psTitle of oChart to "How Much Pizza I Ate Last Night" | |||
WebSet piChartHeight of oChart to 500 | |||
WebSet piChartWidth of oChart to 600 | |||
WebSet psChartType of oChart to sType | |||
Send AddColumn of oChart "Topping" jsonTypeString | |||
Send AddColumn of oChart "Slices" jsonTypeInteger | |||
Send AddData of oChart "Mushrooms" 6 | |||
Send AddData of oChart "Onions" 3 | |||
Send AddData of oChart "Olives" 2 | |||
Send AddData of oChart "Frogs Legs" 1 | |||
Send AddData of oChart "Pepperoni" 4 | |||
Send AddData of oChart "Anchovies" 5 | |||
Send DrawChart of oChart | |||
End_Procedure | |||
Object oChart is a cWebChart | |||
End_Object | |||
End_Object | |||
End_Object | |||
</source> | |||
Note that we only really have to add stuff to one of the radio (OK, ''cWebRadio''!) objects, because they all operate as a set, so oBar, oArea and friends are just vanilla radio objects, while oPie has the added Set pbServerOnChange, OnChange procedure and OnLoad procedure and is the one the DrawChart procedure WebGets the psValue of to know what kind of chart to produce. | |||
Now the Pie Chart will be displayed when the view loads, while the various other chart types will be shown as the user clicks on the appropriate radio buttons. | |||
=== External links === | === External links === | ||
Line 295: | Line 464: | ||
* [https://developers.google.com/chart/ Google Charts official documentation] | * [https://developers.google.com/chart/ Google Charts official documentation] | ||
* [https://support.dataaccess.com/Forums/showthread.php?65704-Basic-sample-of-Google-Chart-working-with-Dataflex-WebApp Forum question that triggered this article] | * [https://support.dataaccess.com/Forums/showthread.php?65704-Basic-sample-of-Google-Chart-working-with-Dataflex-WebApp Forum question that triggered this article] | ||
* [https://support.dataaccess.com/Forums/showthread.php?67286-Google-Bar-Chart-Example&p=364834#post364834 Google Bar Chart by Jarred@TME] | |||
[[Category: Tutorials]] | |||
[[Category: Web Applications]] |
Latest revision as of 18:25, 21 June 2022
By Mike Peat
Below we will create a DataFlex wrapper component for the Google Charts component.
A wrapper consists of multiple parts working together, so that you can use the control directly from your DataFlex web application. The first two elements are the client-side JavaScript part (actually a JavaScript pseudo-class) and the server-side DataFlex class, which together make up the new component.
The JavaScript part
Create a new folder GoogleCharts in your AppHtml folder and put the following in the file Charts.js
(AppHTML\GoogleCharts\Charts.js):
if (!myCharts) { // Configure namespace if not already defined var myCharts = {}; } myCharts.chart = function chart(sName, oParent) { // Forward send constructor myCharts.chart.base.constructor.call(this, sName, oParent); // Load the Visualization API and the corechart package. google.charts.load('current', {'packages':['corechart']}); // Properties: this.prop(df.tString, "psTitle", ""); this.prop(df.tInt, "piChartHeight", 0); this.prop(df.tInt, "piChartWidth", 0); this.prop(df.tString, "psChartType", ""); // Private: this._eWrap = null; this._eCols = []; this._eData = []; // Configure super classes this._sControlClass = "chart"; }; df.defineClass("myCharts.chart", "df.WebBaseControl", { openHtml : function(aHtml) { // Forward send myCharts.chart.base.openHtml.call(this, aHtml); aHtml.push('<div class="chart-wrp">'); aHtml.push(' <div id="', this.psHtmlId, 'chartDiv"', ' style="height: 100%;"></div>'); aHtml.push('</div>'); }, afterRender : function() { this._eControl = df.dom.query(this._eElem, "div.chart-wrp > div"); this._eWrap = df.dom.query(this._eElem, "div.chart-wrp"); // Forward send myCharts.chart.base.afterRender.call(this); }, initalize : function() { this._eCols = []; this._eData = []; }, addColumn : function(sName, iType) { var i = this._eCols.length; this._eCols[i] = [iType, sName]; }, addData : function(sName, nValue) { var i = this._eData.length; this._eData[i] = [sName, Number(nValue)] }, drawChart : function() { myCharts.obj = this; // Set a callback to run when the Google Visualization API is loaded. google.charts.setOnLoadCallback(this.chartDef); }, chartDef : function() { var data = new google.visualization.DataTable(); var options, chart, obj = myCharts.obj; for (var i = 0; i < obj._eCols.length; i++) { data.addColumn(obj._eCols[i][0], obj._eCols[i][1]); } data.addRows(obj._eData); options = { title : obj.psTitle, width : obj.piChartWidth, height : obj.piChartHeight }; switch (obj.psChartType) { case "PieChart": chart = new google.visualization.PieChart(obj._eControl); break; case "BarChart": chart = new google.visualization.BarChart(obj._eControl); break; case "AreaChart": chart = new google.visualization.AreaChart(obj._eControl); break; default: chart = new google.visualization.PieChart(obj._eControl); } chart.draw(data, options); } });
The DataFlex counterpart class
Create a new file called cWebChart.pkg in the AppSrc folder and copy the following in there.
DataFlex class (AppSrc\cWebChart.pkg):
Use cWebBaseControl.pkg Use cJsonObject.pkg // Just to get the types Define C_chartTypePie for "PieChart" Define C_chartTypeBar for "BarChart" Define C_chartTypeArea for "AreaChart" // etc... Class cWebChart is a cWebBaseControl Procedure Construct_Object Forward Send Construct_Object { WebProperty=Client } Property String psTitle { WebProperty=Client } Property Integer piChartHeight { WebProperty=Client } Property Integer piChartWidth { WebProperty=Client } Property String psChartType Set psJSClass to "myCharts.chart" End_Procedure Procedure Initalize Send ClientAction "initalize" End_Procedure Procedure AddColumn String sName Integer iType String[] asParams String sType Case Begin Case (iType = jsonTypeString) Move "string" to sType Case Break Case (iType = jsonTypeInteger) Move "number" to sType Case Break Case (iType = jsonTypeInteger) Move "number" to sType Case Break Case (iType = jsonTypeDouble) Move "number" to sType Case Break Case (iType = jsonTypeBoolean) Move "boolean" to sType Case Break Case Else Move "string" to sType Case End Move sName to asParams[0] Move sType to asParams[1] Send ClientAction "addColumn" asParams End_Procedure Procedure AddData String sName Number nValue String[] asParams Move sName to asParams[0] Move nValue to asParams[1] Send ClientAction "addData" asParams End_Procedure Procedure DrawChart Send ClientAction "drawChart" End_Procedure End_Class
An example web object
Now that we have our component, we need to deploy it, so here is a sample view using it:
Use cWebView.pkg Use cWebPanel.pkg Use cWebForm.pkg Use cWebButton.pkg Use cWebChart.pkg Use cWebRadio.pkg Object oChart is a cWebView Set piWidth to 700 Set psCaption to "Chart" Delegate Set phoDefaultView to Self Object oWebMainPanel is a cWebPanel Set piColumnCount to 12 Object oPie is a cWebRadio Set piColumnSpan to 3 Set psCaption to "Pie Chart" Set psRadioValue to C_chartTypePie End_Object Object oBar is a cWebRadio Set piColumnSpan to 3 Set piColumnIndex to 3 Set psCaption to "Bar Chart" Set psRadioValue to C_chartTypeBar End_Object Object oArea is a cWebRadio Set piColumnSpan to 3 Set piColumnIndex to 6 Set psCaption to "Area Chart" Set psRadioValue to C_chartTypeArea End_Object Object oDrawChart is a cWebButton Set piColumnSpan to 2 Set psCaption to "Show Chart" Procedure OnClick String sType Send Initalize of oChart WebGet psValue of oPie to sType WebSet psTitle of oChart to "How Much Pizza I Ate Last Night" WebSet piChartHeight of oChart to 500 WebSet piChartWidth of oChart to 600 WebSet psChartType of oChart to sType Send AddColumn of oChart "Topping" jsonTypeString Send AddColumn of oChart "Slices" jsonTypeInteger Send AddData of oChart "Mushrooms" 6 Send AddData of oChart "Onions" 3 Send AddData of oChart "Olives" 2 Send AddData of oChart "Frogs Legs" 1 Send AddData of oChart "Pepperoni" 4 Send AddData of oChart "Anchovies" 5 Send DrawChart of oChart End_Procedure End_Object Object oChart is a cWebChart End_Object End_Object End_Object
Add new control to your app
In order to be able to use that new control, you have to add it to the index.html file like so:
... <!-- DataFlex Custom Controls (do not remove this line, used for automatic insertion) --> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <script src="GoogleCharts/Charts.js"></script> <!-- Initialization of the WebApp --> ...
Screenshots and example workspace
You can download a completely functional DataFlex 19.1 Workspace down here, unzip, register in DataFlex 19.1, let the Studio create the javascript engine folders and run:
File:GoogleChartsDemo-20200326.zip
Addendum...
Never one to leave well enough alone, I have been playing further...
In the JavaScript, I extended the "switch" statement in the chartDef function as follows:
switch (obj.psChartType) { case "PieChart": chart = new google.visualization.PieChart(obj._eControl); break; case "BarChart": chart = new google.visualization.BarChart(obj._eControl); break; case "AreaChart": chart = new google.visualization.AreaChart(obj._eControl); break; case "ColChart": chart = new google.visualization.ColumnChart(obj._eControl); break; case "LineChart": chart = new google.visualization.LineChart(obj._eControl); break; case "ScatterChart": chart = new google.visualization.ScatterChart(obj._eControl); break; default: chart = new google.visualization.PieChart(obj._eControl); }
In order to include more chart types.
In the DataFlex class, all that changed was the definition of some new constants:
Define C_chartTypePie for "PieChart" Define C_chartTypeBar for "BarChart" Define C_chartTypeArea for "AreaChart" Define C_chartTypeScat for "ScatterChart" Define C_chartTypeLine for "LineChart" Define C_chartTypeCol for "ColChart" // etc...
Then in the sample view (Chart.wo), I got rid of the button and just had the radio controls themselves set things off:
Use cWebView.pkg Use cWebPanel.pkg Use cWebForm.pkg Use cWebButton.pkg Use cWebChart.pkg Use cWebRadio.pkg Object oChart is a cWebView Set piWidth to 1000 Set psCaption to "Chart" Delegate Set phoDefaultView to Self Object oWebMainPanel is a cWebPanel Set piColumnCount to 12 Object oPie is a cWebRadio Set piColumnSpan to 2 Set psCaption to "Pie Chart" Set psRadioValue to C_chartTypePie Set pbServerOnChange to True Procedure OnChange Send DrawChart End_Procedure Procedure OnLoad Send DrawChart End_Procedure End_Object Object oBar is a cWebRadio Set piColumnSpan to 2 Set piColumnIndex to 2 Set psCaption to "Bar Chart" Set psRadioValue to C_chartTypeBar End_Object Object oArea is a cWebRadio Set piColumnSpan to 2 Set piColumnIndex to 4 Set psCaption to "Area Chart" Set psRadioValue to C_chartTypeArea End_Object Object oColumn is a cWebRadio Set piColumnSpan to 2 Set piColumnIndex to 6 Set psCaption to "Column Chart" Set psRadioValue to C_chartTypeCol End_Object Object oLine is a cWebRadio Set piColumnSpan to 2 Set piColumnIndex to 8 Set psCaption to "Line Chart" Set psRadioValue to C_chartTypeLine End_Object Object oScatter is a cWebRadio Set piColumnSpan to 2 Set piColumnIndex to 10 Set psCaption to "Scatter Chart" Set psRadioValue to C_chartTypeScat End_Object Procedure DrawChart String sType Send Initalize of oChart WebGet psValue of oPie to sType WebSet psTitle of oChart to "How Much Pizza I Ate Last Night" WebSet piChartHeight of oChart to 500 WebSet piChartWidth of oChart to 600 WebSet psChartType of oChart to sType Send AddColumn of oChart "Topping" jsonTypeString Send AddColumn of oChart "Slices" jsonTypeInteger Send AddData of oChart "Mushrooms" 6 Send AddData of oChart "Onions" 3 Send AddData of oChart "Olives" 2 Send AddData of oChart "Frogs Legs" 1 Send AddData of oChart "Pepperoni" 4 Send AddData of oChart "Anchovies" 5 Send DrawChart of oChart End_Procedure Object oChart is a cWebChart End_Object End_Object End_Object
Note that we only really have to add stuff to one of the radio (OK, cWebRadio!) objects, because they all operate as a set, so oBar, oArea and friends are just vanilla radio objects, while oPie has the added Set pbServerOnChange, OnChange procedure and OnLoad procedure and is the one the DrawChart procedure WebGets the psValue of to know what kind of chart to produce.
Now the Pie Chart will be displayed when the view loads, while the various other chart types will be shown as the user clicks on the appropriate radio buttons.