Basic example of Google Charts with DataFlex WebApp: Difference between revisions

From DataFlex Wiki
Jump to navigationJump to search
Addendum
m other
Line 458: Line 458:
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.
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 chart types will be shown as the user clicks on the appropriate radio buttons.
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 ===

Revision as of 14:42, 27 March 2020

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

Pie Chart Demo


Bar Chart Demo


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:

        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.

External links