Use Plotly in PivotTable

Hi,

According to the documentation, PivotTable support the use of Plotly and thereby showing pie charts. Is this something that can be used within Cuba? And if so, how?

Thanks for any help.

Regards
-b

Any news on this one?

Hello!

Unfortunately, CUBA PivotTable allows to use only a predefined set of renderers.

Hi @Pinyazhin,

Thanks for your update. Is there any way we could add them ourselves? Maybe by extending parts of the implementation?

Regards
-b

Well, you can extend server-side and client-side widgets. Pie chart renderer is provided in 2.23.0 version of pivottable.js that is not tested in CUBA (current version 2.21.0). Probably, it may lead to some bugs.

The way we extend PivotTable similar to this manual Creating a GWT component.

  1. Create inheritor of CubaPivotTable widget and add JavaScript library for Plotly renderers:
@JavaScript({
        "https://cdn.plot.ly/plotly-basic-latest.min.js",
        "https://cdnjs.cloudflare.com/ajax/libs/pivottable/2.23.0/plotly_renderers.min.js"})
public class MyCubaPivotTable extends CubaPivotTable {

    public MyCubaPivotTable(PivotTableSerializer pivotTableSerializer) {
        super(pivotTableSerializer);
    }
}
  1. Create inheritor of WebPivotTable component which will create widget above:
public class MyWebPivotTable extends WebPivotTable implements PivotTable {

    protected CubaPivotTable createComponent() {
        return new MyCubaPivotTable(createPivotTableSerializer());
    }
}

Then we need to override JS library version by newer one. Create in web module folders: “VAADIN/webjars/pivottable/2.21.0.cuba.0” and place JS files from 2.23.0 version. Do not forget to register component (see How is the way to extends Components like Button).

Create web-tookit module and extend CubaPivotTableSceneConnector, CubaPivotTableSceneWidget and add Plotly renderers to the configuration:

private static native void addPlotlyRenderers(JavaScriptObject config) /*-{
    config.options.renderers = $wnd.$.extend(
	                        $wnd.$.pivotUtilities.renderers,
                            $wnd.$.pivotUtilities.plotly_renderers);
}-*/;

The full demo project: pvtdemo.zip (104.6 KB)

It is not the best solution as it forced change renderers, and probably it does not support localization.

1 Like

Hi @Pinyazhin,

This is really great. We will use this as a basis to go forward. Glad that there is at least an option to get something like this in place.

Thanks a lot!!

Regards,
-b

Hi @Pinyazhin,

I’ve tried your demo and it works very nice and exactly what we were hoping for. So we are now integrating it into our Cuba application.

We are still on 6.10 (although we hope to migrate to 7+ very soon) and I needed to make some adjustments. I think I got it running but somehow the plotly renders are initialised before the pivot table is initialised. As a result, there is an error (it misses the $.pivotUtilities that is set through the pivot table initialisation) and no plotly renderes are loaded.

Any idea why the plotly renderers are initialised before the pivot table? Is there any way to make some adjustments in this order?

Any help appreciated.

Regards,
-b

Hello,

it seems the order of loading resources was changed in 7.0+ versions.

Try to download plotly_renderers.min.js and place it to VAADIN/webjars/pivottable/2.21.0.cuba.0.
Change inheritor of CubaPivotTable as follows:

@JavaScript("https://cdn.plot.ly/plotly-basic-latest.min.js")
@WebJarResource("pivottable:plotly_renderers.min.js")
public class MyCubaPivotTable extends CubaPivotTable {

Hi @Pinyazhin,

Your suggestion made it work, great! Really appreciate your help.

I guess there is no way to control the applied renderer, e.g. pie chart, from within the application? We do see the option appear in the browser (just as in the demo project) but cannot select a certain renderer from the screen controller, e.g.:

   pivotTable.getRenderers().setSelectedRenderer(Renderer.MULTIPLE_PIE_CHART);
   pivotTable.repaint();

We use this to set certain pre-defined settings to the Pivot table depending on user preference (so they cannot be set in the screen descriptor as they will change per session / user etc.

Could we somehow extend the implementation even further to allow such functionality? The only thing that would need an extension seems to be the enum Renderer in com.haulmont.charts.gui.pivottable.model but there seems no way to extend or override this implementation.

Again, any help appreciated.

Regards,
-b

Yes, you can add your method that will set default Plotly renderer. You should extend CubaPivotTableSceneState in the web module under the package: my.company.package.web.toolkit.ui.client:

public class MyPivotTableSceneState extends CubaPivotTableSceneState {
    @DelegateToWidget
    public String plotlyRenderer;
}

Client widget code will be changed as follows:

MyPivotTableSceneWidget
public class MyPivotTableSceneWidget extends CubaPivotTableSceneWidget {

    protected String plotlyRenderer;

    @Override
    public void init(PivotTableConfig config, PivotTableEvents events) {
        addPlotlyRenderers(config, plotlyRenderer);

        super.init(config, events);
    }

    private static native void addPlotlyRenderers(JavaScriptObject config, String plotlyRenderer) /*-{
        config.options.renderers = $wnd.$.extend(
    	                        $wnd.$.pivotUtilities.renderers,
                                $wnd.$.pivotUtilities.plotly_renderers);

        if (plotlyRenderer) {
            config.options.rendererName = plotlyRenderer;
        }
    }-*/;

    public void setPlotlyRenderer(String plotlyRenderer) {
        this.plotlyRenderer = plotlyRenderer;
    }
}

Then in the connector and MyCubaPivotTable override getState() methods. Provide methods to get/set plotlyRenderer.

See the full example: demo.zip (104.6 KB)

Hi @Pinyazhin,

This is really great - works like a charm. Will need to do some more to get everything working as expected but I think I can manage from here. Thank you very much!

By the way, wouldn’t it be a good idea to switch to 2.23.0+ of the PivotTable and include the plotly renderer by default? It provide many more advantages over c3 and given your approach here I think it would be fairly easy to do, correct?

Regards,
-b

Hi @b.tel,

Thank you for the suggestion. I’ve created an issue for this functionality: cuba-platform/charts#105.

Great! Hope it is taken up soon.

Thanks for all the excellent support!

Hi @Pinyazhin,

I have it up and running within our own application but I’m still struggling with the size of the charts that are generated. It seems they are derived from or related to the total window size and it is impossible to change them. This seems default behavior.

Plotly with PivotTable allows to modify the size and stuff by setting layout parameters as RendererOptions. These are however limited to C3 options and some heatmap functions.

Could they be extended to handle Plotly parameters as well? I’ve looked at the implementation and it seems that the RendererOptions class could be extended to include Plotly parameters but it seems not possible to actually have them set in the PivotTable component as shown on screen (browser).

Any ideas how this could be supported? I would not need to have all layout options to be supported but size, title and legend would be very convenient.

Thanks for any help - much appreciated.

Regards
-b

PS: would be great if the chart:rendererOptions/ would allow for something like:

                <chart:rendererOptions>
                    <![CDATA[{
                        plotly: { 
                             layout: {
                                  width: 500,
                                  height: 500,
                                  showLegend: false
                             }
                        }
                    }]]>
                </chart:rendererOptions>

Hi @Pinyazhin,

Still struggling to get something working here and tried to follow the same solution pattern as you applied for setting the renderer. Thus, the MyPivotTableSceneWidget.java now has some extra functions including:

    private static native void addPlotlyConfig(JavaScriptObject config, String plotlyConfig) /*-{
        if (plotlyConfig) {
           config.options.rendererOptions = plotlyConfig;
        }
    }-*/;

    public void setPlotlyConfig(String plotlyConfig) {
        this.plotlyConfig = plotlyConfig;
    }

Where the plotlyConfig is a JSON configuration for plotly, e.g.:

plotly: { 
           layout: {
                width: 500,
                height: 500,
                showLegend: false
           }
        } 

Corresponding functions etc. exists in the other classes as well, just as setting the plotly renderer.

But there isn’t any change / effect. And to be honest, I do not know what to think of these strange commented native functions.

Any suggestions on this topic?

Regards
-b

Hello @b.tel,

github wiki says that “plotly” key is merged to the “layout” object, so you can try:

plotly: { 
   width: 500,
   height: 500,
   showLegend: false
}

For instance:

private static native void addPlotlyRenderers(JavaScriptObject config) /*-{
    config.options.renderers = $wnd.$.extend(
                            config.options.renderers,
                            $wnd.$.pivotUtilities.plotly_renderers);

    var plotlyOptions = {
       plotly: {
            width: 500,
            height: 500
       }
    };

    if (config.options.rendererOptions) {
        $wnd.$.extend(config.options.rendererOptions, plotlyOptions);
    } else {
        config.options.rendererOptions = plotlyOptions;
    }
}-*/;
1 Like

Hi @Pinyazhin,

Totally missed that remark about having merged the layout object into the plotly key. But based with this information and your code sample (I was close but apparently not close enough) I got things working.

Really appreciate your support. Thanks a lot!

Regards,
-b