Primefaces 5.0 charts – how to create chart models and series dynamically entirely from database values

I am trying to create charts which dynamically respond to values from a DB concerning the type of charts, chart models and chart series.

Most of the examples and questions I have seen only seem to deal with statically defining chart models and chart series. I want to dynamically control what type of charts are shown, the chart models and series shown entirely by changing values in the database (through a back office or content management interface). I have already developed the back office content management system (CMS).

This question is about how to adapt the PF showcase examples or APIs to an entirely dynamic model that lets the back office define the type, model and series of charts.

The below example tries to generate a barchart from 3 mySql tables:

1) Endataset: a table containing the datasets defined by primary key ‘idmid’ 2) Endataseries: a table containing the data series which has a OneToMany relationship with Endataset – defined by ‘recid’ 3) Endatapoint: table with the actual data values (numbers and dates) defined by ‘pointid’

I want to return a BarChartModel and ChartSeries for each dataset (idmid) as a list of different charts according to whatever is set by the back office. In other words, I want to dynamically create chart models and series according to however many values (datasets) are in the database. I’m able to return a graph using the example below but it is showing 3 series in 2 of the same models, rather than 2 series in one model and 1 series in a second model (which is my aim).

My jsf:

 <p:dataGrid id="cgridtest" value="#{chartTestBean.testTopList}" var="chars">
  <p:panel>
  <p:chart id="gridcharts" type="#{chartTestBean.chartType}" 
   model="#{chartTestBean.testModel}"style="width: 150px; height: 150px"/>
    </p:panel>
   <h:outputText value="#{chars.idmid}"/>
   </p:dataGrid>

The bean methods:

public List<Endataset> getTestTopList() {
    testTopList = processChartList();
    return testTopList;
}

public List<Endataset> processChartList() {
    chartType = "bar";
    orig = guestChartFacade.findAll();
    sers = new ArrayList();
    for (int n = 0; n < orig.size(); n++) {
        idmid = orig.get(n).getIdmid();
        selJoin = guestChartFacade.find(idmid);

        startDate = selJoin.getStartdate();
        sers.add(idmid);
    }

    dsetList = setfacade.findTopsRange(sers);
    testTopList = new ArrayList();
    barmod = new ArrayList();
    for (int d = 0; d < dsetList.size(); d++) {

        testModel = new BarChartModel();
        chartSer = new ChartSeries();
        idmid = dsetList.get(d).getIdmid();
        selSet = setfacade.find(idmid);

        testTopList.add(selSet);

        barmod.add(testModel);

        showMods();

    }
    return testTopList;
}

public BarChartModel showMods() {

    for (BarChartModel t : barmod) {

        testModel = t;
        pointList = new ArrayList();

        pointList = pointFacade.pointRangeIdmid(idmid, startDate);

        for (Endatapoint p : pointList) {
            chartSer.set(p.getRecords().getSeriesname(), p.getActualnum());

        }
        testModel.addSeries(chartSer);

        return testModel;
    }
    return null;
}

The below example is meant to return share prices of two companies at a given date. There is a third series which should be returned in a separate chart model, but as shown below, all 3 series are appearing in a single model which suggests that separate instances of the BarChartModel are not being created for each dataset. Would appreciate any guidance on how to create separate chart models for each dataset using this example. Thanks in advance for any help.

enter image description here

Answer

After some research the answer seems to be to use separate models for each type of chart you want to create. In the below example i’m creating models for Barchart and linechart, which could be extended to use any other chart types supported by PF. in the EL I’m calling the list arrays (ie [0]), but this is not necessary and was just my preference. Also I extended the PF BarChartModel class (ExtendedBarChartModel), but the example works fine if you use the standard BarChartModel.

Hope this helps and any feedback welcome:

<p:dataGrid id="modellist" value="#{chartTestBean.xbarmod[0]}" var="barmd">
<p:chart id="gridchart" type="bar" model="#{barmd}" style="width: 150px; height: 150px"/>
</p:dataGrid>

<p:dataGrid id="linegrid" value="#{chartTestBean.linemodelList[0]}" var="linemod">
<p:chart id="linechart" type="line" model="#{linemod}" style="width: 150px; height: 150px"/> 
</p:dataGrid>
.... Other chart models as needed here

The bean methods for the bar chart model:

public List<ExtendedBarModel> ModelList() {
    xbarmod = new ArrayList();
    sers = new ArrayList();

    //chartType = "bar";
    orig = guestChartFacade.findAll();

    for (Enguestjoinchart j : orig) {
        if (j.getCharttype().equals("bar")) {
            setChartType("bar");
            showBar = true;
            idmid = j.getIdmid();
            selJoin = guestChartFacade.find(idmid);
            startDate = selJoin.getStartdate();
            sers.add(idmid);
        }
    }

    dsetList = setfacade.findTopsRange(sers);

    processModelList();
    return xbarmod;
}


public ExtendedBarModel processModelList() {
    for (int i = 0; i < dsetList.size(); i++) {

        idmid = dsetList.get(i).getIdmid();

        pointList = pointFacade.pointRangeIdmid(idmid, startDate);
        xtestmodel = new ExtendedBarModel("Barmodel " + dsetList.get(i).getIdmid());

        chartSer = new ChartSeries();
        for (Endatapoint p : pointList) {
            chartSer.set(p.getRecords().getSeriesname(), p.getActualnum());

        }
        xtestmodel.addSeries(chartSer);
        xbarmod.add(xtestmodel);
    }

    for (ExtendedBarModel b : xbarmod) {
        xtestmodel = b;
        return xtestmodel;
    }
    return null;
}

For the line chart:

public List<LineChartModel> makelinelistModel() {
    linemodelList = new ArrayList();
    linesers = new ArrayList();

    orig = guestChartFacade.findAll();

    for (Enguestjoinchart w : orig) {
        if (w.getCharttype().equals("line")) {
            idmidLine = w.getIdmid();
            selJoinLine = guestChartFacade.find(idmidLine);

            startDateLine = guestChartFacade.findStart(idmidLine);

            endDateLine = guestChartFacade.findEnd(idmidLine);
            linesers.add(idmidLine);
            showLine = true;
        }
    }

    if (linesers.size()==0) {
        dsetlineList = null;
        linemodelList = null;

    } 
    else {
       dsetlineList = setfacade.findTopsRange(linesers);
        processLineModelList();
    }
    return linemodelList;

}

public LineChartModel processLineModelList() {
    for (int i = 0; i < dsetlineList.size(); i++) {

        idmidLine = dsetlineList.get(i).getIdmid();
        pointListLine = pointFacade.pointLineRange(idmidLine, startDateLine, endDateLine);
        linemodel = new LineChartModel();

        chartSerLine = new ChartSeries();
        Map<Object, Number> datMap = new HashMap();
        DateAxis axis = new DateAxis();

        for (Endatapoint p : pointListLine) {
            chartSerLine.set(p.getPointdate().toString(), p.getActualnum());
            linemodel.addSeries(chartSerLine);

        }

        linemodelList.add(linemodel);
        linemodel.getAxes().put(AxisType.X, axis);
    }

    for (LineChartModel m : linemodelList) {
        linemodel = m;
        return linemodel;
    }
    return linemodel;
}

.... Other chart models

Leave a Reply

Your email address will not be published. Required fields are marked *