Skip to content

Creating my own widget #18

Description

@Tixierae

I followed the exact template of your Gauge widget to try to create a histogram widget (.js and .R files below).

The core of the .js file works. If you just paste the whole var chart = c3.generate({...}) statement into http://c3js.org/samples/chart_bar.html, adding the lines

var x = {
"x1":[0, 50, 100, 150, 200, 250],
"prob":[0.3, 0.2, 0.1, 0.05, 0.04, 0.01],
"my_th":2
};

at the top, the histogram shows as expected. However, when executing

C3Hist(x1=c(0, 50, 100, 150, 200, 250),prob=c(0.3, 0.2, 0.1, 0.05, 0.04, 0.01),my_th=2)

in RStudio, nothing shows. So, I believe that my bindings are at fault, but I couldn't find what's wrong. Could you please have a quick look? Your help would be much appreciated.

If you need to reproduce the error, you can install my fork of C3 with devtools::install_github("tixierae/shinyJsTutorials/tutorials/materials2/C3"). Note that I created a C3Hist.yaml file, and added export(C3Hist);export(C3HistOutput) to the NAMESPACE file.

C3Hist.R

C3Hist <- function(prob,x1,my_th,width=NULL,height=NULL) {
  # forward options using x
  x = list(
    prob = prob,
    x1 = x1,
    my_th = my_th
  )
  # create widget
  htmlwidgets::createWidget(
    name = 'C3Hist',
    x,
    width = width,
    height = height,
    package = 'C3'
  )
}
C3HistOutput <- function(outputId, width = '100%', height = '400px'){
  htmlwidgets::shinyWidgetOutput(outputId, 'C3Hist', width, height, package = 'C3')
}
renderC3Hist <- function(expr, env = parent.frame(), quoted = FALSE) {
  if (!quoted) { expr <- substitute(expr) } # force quoted
  htmlwidgets::shinyRenderWidget(expr, C3HistOutput, env, quoted = TRUE)
}

C3Hist.js

HTMLWidgets.widget({
    name: 'C3Hist',
    type: 'output',
    factory: function(el, width, height) {
        // create an empty chart
        var chart = null;
        return {
            renderValue: function(x) {
                // check if the chart exists
                if(chart === null){
                    // the chart did not exist and we want to create a new chart via c3.generate
                    var chart = c3.generate({  
                        bindto : el,
                        data: {
                            columns: [
                                ['x1'].concat(x.x1),
                                ['prob'].concat(x.prob)
                            ],
                            type: 'bar',
                            xs: {
                                'prob': 'x1', 
                            },
                            colors: {
                                prob: function(d) {
                                    return (x.prob.indexOf(d.value) >= x.my_th) ? '#aec7e8':'#1f77b4';
                                }
                            },
                            onclick:  function (d, element) {Shiny.onInputChange(el.id,d)}
                        },
                        bar: {
                            width: {
                                ratio: 1 // this makes bar width 100% of length between ticks
                            }
                        },
                        legend: {
                            show: false
                        },
                        // take care of color in tooltip
                        tooltip: {
                            contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
                                color = function() {
                                    return (x.prob.indexOf(d[0].value) >= x.my_th) ? '#aec7e8':'#1f77b4';
                                };
                                return chart.internal.getTooltipContent.call(this, d, defaultTitleFormat, defaultValueFormat, color)
                            }
                        }
                    });
                    // store the chart on el so we can get it latter
                    el.chart = chart;
                }
                // at this stage the chart always exists
                // load the new data
                chart.load({
                    columns: [
                        ['x1'].concat(x.x1),
                        ['prob'].concat(x.prob)
                    ]
                });
            },
            resize: function(width, height) {
                // this will vary based on the JavaScript library
                // in the case of C3 we are fortunate that there is a resize method
                //  http://c3js.org/samples/api_resize.html
                chart.resize({height:height, width:width})
            }
        };
    }
});

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions