shinyJsTutorials
shinyJsTutorials copied to clipboard
Creating my own widget
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})
}
};
}
});