Closed debsush closed 8 years ago
Hi,
Your problem is how to access to an existing chart within shiny and javascript function.
As you can see here (http://stackoverflow.com/questions/28384411/get-an-instance-of-amchart-using-id), amCharts
have AmCharts.charts
array with all amCharts graphics, and so we can get a chart by his id.
To simplify this, and have a simply functionnality, I've just add getAmChart()
javascript function to get and then modify a chart. So now, you can use all the methods you want ! Here is a simple example with two graphics :
require(shiny)
require(rAmCharts)
require(shinyjs)
jsCode <- "shinyjs.changeType = function(params){
var chart = getAmChart(params[1]);
chart.graphs[0].type = params[0];
chart.validateNow();
}"
server <- function(input, output) {
output$myplot1 <- renderAmCharts({
##Data
data('data_bar')
##Plot
graph <- pipeR::pipeline(
amSerialChart(categoryField = 'country'),
setDataProvider(data_bar),
addGraph(balloonText = '<b>[[category]]: [[value]]</b>', type = "line", valueField = 'visits')
)
graph
})
output$myplot2 <- renderAmCharts({
##Data
data('data_bar')
##Plot
graph <- pipeR::pipeline(
amSerialChart(categoryField = 'country'),
setDataProvider(data_bar),
addGraph(balloonText = '<b>[[category]]: [[value]]</b>', type = "column", valueField = 'visits')
)
graph
})
observeEvent(input$type1, {
js$changeType(input$type1, "myplot1")
})
observeEvent(input$type2, {
js$changeType(input$type2, "myplot2")
})
}
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jsCode),
sidebarLayout(
sidebarPanel(
selectInput("type1", "Type of graph 1 :", c("line", "column")),
selectInput("type2", "Type of graph 2 :", c("column", "line"))
),
mainPanel(amChartsOutput("myplot1"), amChartsOutput("myplot2"))
)
)
shinyApp(ui = ui, server = server)
Excellent. Much appreciate. This is great.
Similarly is there a way by which I can use a R data frame within the addListner JS function. I am referencing this example and would like to replicate it in R Shiny http://www.amcharts.com/tips/change-the-data-set-dynamically-based-on-zoom-on-stock-chart/
I am struggling to replicate the above example for months and would greatly appreciate an implementation of the same from your end
Example outlined
output$plotter<-renderAmCharts({
##Data
data('data_bar') # Dataset 1#
data('data_bar1') #Dataset 2#
##Plot
graph <- pipeR::pipeline(
amSerialChart(categoryField = 'country'),
setDataProvider(data_bar),
addGraph(balloonText = '<b>[[category]]: [[value]]</b>', type = "column", valueField = 'visits')%>>%
addListener('zoomed', paste('function(event) {
var startdt = event.chart.startDate;
var enddt = event.chart.endDate;
var timeDiff = Math.abs(end.getTime() - start.getTime());
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
if (diffDays < 365) {
chart.mainDataSet.dataProvider = data_bar; /* this is where I need to either access R data frame or run a R function that pulls the data. I guess we would need to convert R data frame to JSON*/
chart.validateNow(false, true);
})
)
graph
})
You can use the same way as passing some basic input like the type, with good data transformation :
rAmCharts:::.toList(data_bar)
for transform data.frame to listjsonlite::toJSON(data_list)
with good arguments (http://www.htmlwidgets.org/develop_advanced.html)I will give this a try today. Sounds interesting
Hi,
The above example you gave using shinyjs did not work on my system. When I change the chart type, it does not change the chart. Is this because while we are changing thhe chart configuration using JS, but it is not getting re-rendered within renderAmCharts and hence yielding no results. Can you check if it is working at your end.
If the above example is working at your end, can you provide me your session info
Thank you SD
The example works for me, using last shiny
and shinyjs
CRAN version, and last rAmCharts
github developpment version
I will try that
The example with SerialChart works but the one with AmStockChart below does not. Please help me understand the issue
#paste("shinyjs.changeType = function(params){var chart = getAmChart(params[1]);chart.graphs[0].type = ",df,";chart.validateNow();}",sep="")
require(shiny)
require(rAmCharts)
require(shinyjs)
jsCode <- "shinyjs.changeType = function(params){
var chart = getAmChart(params[1]);
chart.graphs[0].type = params[0];
chart.validateNow();
}"
server <- function(input, output) {
output$myplot1 <- renderAmCharts({
##Data
data('data_bar')
##Plot
graph <- pipeR::pipeline(
amSerialChart(categoryField = 'country'),
setDataProvider(data_bar),
addGraph(balloonText = '<b>[[category]]: [[value]]</b>', type = "line", valueField = 'visits')
)
graph
})
output$myplot2 <- renderAmCharts({
# ##Data
# data('data_bar')
# ##Plot
# graph <- pipeR::pipeline(
# amSerialChart(categoryField = 'country'),
# setDataProvider(data_bar),
# addGraph(balloonText = '<b>[[category]]: [[value]]</b>', type = "column", valueField = 'visits')
# )
## Data
times <- as.POSIXct(seq(-60 * 60 * 24 * 50 + 1, 0, by = 3600), origin = Sys.time(), tz = 'UTC')
times <- round(times,'hours')
times <- data.frame(times)
times$Mesure <- 1:length(times$times) + rep(cos(seq(-pi,pi,length.out = 100)), 12) * 500 + runif(length(times$times)) * 200
mycategoryBalloonDateFormat <- list(list(period = 'YYYY', format = 'YYYY'),
list(period='MM', format = 'YYYY-MM'),
list(period = 'WW', format = 'YYYY-MM-DD'),
list(period='DD', format = 'YYYY-MM-DD'),
list(period = 'hh', format = 'YYYY-MM-DD JJ:NN'),
list(period='mm', format = 'YYYY-MM-DD JJ:NN'),
list(period = 'ss', format = 'YYYY-MM-DD JJ:NN:ss'),
list(period='fff', format = 'YYYY-MM-DD JJ:NN:ss'))
## Plot
graph<-pipeR::pipeline(
amStockChart(dataDateFormat = 'YYYY-MM-DD JJ:NN:ss') ,
addDataSet(pipeR::pipeline(
dataSet(title = 'first data set', categoryField = 'times') ,
setDataProvider(times,keepNA=FALSE),
addFieldMapping(fromField = 'Mesure', toField = 'Mesure'))),
addPanel(pipeR::pipeline(
stockPanel(showCategoryAxis = TRUE, title = 'Value') ,
addStockGraph(id = 'g1',connect=FALSE, valueField = 'Mesure', comparable = TRUE,periodValue = 'Average',type='column',
compareField = 'Mesure', balloonText = 'Value : <b>[[value]] Unit</b>', precision = 0,
compareGraphBalloonText = '[[title]] =<b>[[value]]</b>'))),
setChartScrollbarSettings(graph = 'g1'),
setChartCursorSettings( valueBalloonsEnabled = TRUE, fullWidth = TRUE,
cursorAlpha = 0.1, valueLineBalloonEnabled = TRUE,
valueLineEnabled = TRUE, valueLineAlpha = 0.5,
categoryBalloonDateFormats = mycategoryBalloonDateFormat),
setPeriodSelector(pipeR::pipeline( periodSelector( position = 'bottom' ,inputFieldsEnabled=FALSE) ,
addPeriod( period = 'DD', selected = TRUE, count = 1, label = '1 day') ,
addPeriod( period = 'WW', count = 1, label = '1 week' ) ,
addPeriod( period = 'MAX', label = 'All' ))),
setCategoryAxesSettings(parseDates = TRUE, minPeriod = '1hh',
groupToPeriods = c('hh','3hh', '12hh','1DD'),maxSeries = 50),
setPanelsSettings(recalculateToPercents = 'never', creditsPosition='top-left')
)
graph
})
observeEvent(input$type1, {
js$changeType(input$type1, "myplot1")
})
observeEvent(input$type2, {
js$changeType(input$type2, "myplot2")
})
}
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jsCode),
sidebarLayout(
sidebarPanel(
selectInput("type1", "Type of graph 1 :", c("line", "column")),
selectInput("type2", "Type of graph 2 :", c("column", "line"))
),
mainPanel(amChartsOutput("myplot1"), amChartsOutput("myplot2"))
)
)
shinyApp(ui = ui, server = server)
Hi,
First, issue on github is for bug/update for the R package, not for ask another question (problem in javascript, error in R code, ....)
In your case, the javascript code is wrong. serial
and stock
don't have the same structure. So you have to look at the amChart API or use some things as console.info
in javascript to do what you want and view object in web console for example.
I`ve corrected your case today but please post real issue in the futur.
#paste("shinyjs.changeType = function(params){var chart = getAmChart(params[1]);chart.graphs[0].type = ",df,";chart.validateNow();}",sep="")
require(shiny)
require(rAmCharts)
require(shinyjs)
jsCode <- "shinyjs.changeType = function(params){
var chart = getAmChart(params[1]);
console.info(chart);
if(chart !== undefined){
if(chart.type === 'serial'){
chart.graphs[0].type = params[0];
} else if(chart.type === 'stock') {
chart.panels[0].graphs[0].type = params[0];
}
chart.validateNow();
}
}"
server <- function(input, output) {
output$myplot1 <- renderAmCharts({
##Data
data('data_bar')
##Plot
graph <- pipeR::pipeline(
amSerialChart(categoryField = 'country'),
setDataProvider(data_bar),
addGraph(balloonText = '<b>[[category]]: [[value]]</b>', type = "line", valueField = 'visits')
)
graph
})
output$myplot2 <- renderAmCharts({
# ##Data
# data('data_bar')
# ##Plot
# graph <- pipeR::pipeline(
# amSerialChart(categoryField = 'country'),
# setDataProvider(data_bar),
# addGraph(balloonText = '<b>[[category]]: [[value]]</b>', type = "column", valueField = 'visits')
# )
## Data
times <- as.POSIXct(seq(-60 * 60 * 24 * 50 + 1, 0, by = 3600), origin = Sys.time(), tz = 'UTC')
times <- round(times,'hours')
times <- data.frame(times)
times$Mesure <- 1:length(times$times) + rep(cos(seq(-pi,pi,length.out = 100)), 12) * 500 + runif(length(times$times)) * 200
mycategoryBalloonDateFormat <- list(list(period = 'YYYY', format = 'YYYY'),
list(period='MM', format = 'YYYY-MM'),
list(period = 'WW', format = 'YYYY-MM-DD'),
list(period='DD', format = 'YYYY-MM-DD'),
list(period = 'hh', format = 'YYYY-MM-DD JJ:NN'),
list(period='mm', format = 'YYYY-MM-DD JJ:NN'),
list(period = 'ss', format = 'YYYY-MM-DD JJ:NN:ss'),
list(period='fff', format = 'YYYY-MM-DD JJ:NN:ss'))
## Plot
graph<-pipeR::pipeline(
amStockChart(dataDateFormat = 'YYYY-MM-DD JJ:NN:ss') ,
addDataSet(pipeR::pipeline(
dataSet(title = 'first data set', categoryField = 'times') ,
setDataProvider(times,keepNA=FALSE),
addFieldMapping(fromField = 'Mesure', toField = 'Mesure'))),
addPanel(pipeR::pipeline(
stockPanel(showCategoryAxis = TRUE, title = 'Value') ,
addStockGraph(id = 'g1',connect=FALSE, valueField = 'Mesure', comparable = TRUE,periodValue = 'Average',type='column',
compareField = 'Mesure', balloonText = 'Value : <b>[[value]] Unit</b>', precision = 0,
compareGraphBalloonText = '[[title]] =<b>[[value]]</b>'))),
setChartScrollbarSettings(graph = 'g1'),
setChartCursorSettings( valueBalloonsEnabled = TRUE, fullWidth = TRUE,
cursorAlpha = 0.1, valueLineBalloonEnabled = TRUE,
valueLineEnabled = TRUE, valueLineAlpha = 0.5,
categoryBalloonDateFormats = mycategoryBalloonDateFormat),
setPeriodSelector(pipeR::pipeline( periodSelector( position = 'bottom' ,inputFieldsEnabled=FALSE) ,
addPeriod( period = 'DD', selected = TRUE, count = 1, label = '1 day') ,
addPeriod( period = 'WW', count = 1, label = '1 week' ) ,
addPeriod( period = 'MAX', label = 'All' ))),
setCategoryAxesSettings(parseDates = TRUE, minPeriod = '1hh',
groupToPeriods = c('hh','3hh', '12hh','1DD'),maxSeries = 50),
setPanelsSettings(recalculateToPercents = 'never', creditsPosition='top-left')
)
graph
})
observeEvent(input$type1, {
js$changeType(input$type1, "myplot1")
})
observeEvent(input$type2, {
js$changeType(input$type2, "myplot2")
})
}
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jsCode),
sidebarLayout(
sidebarPanel(
selectInput("type1", "Type of graph 1 :", c("line", "column")),
selectInput("type2", "Type of graph 2 :", c("column", "line"))
),
mainPanel(amChartsOutput("myplot1"), amChartsOutput("myplot2"))
)
)
shinyApp(ui = ui, server = server)
Cheers
Apologies. I will take care of it going forward. Thank you as always.
Your package manual/documentation rAmcharts.pdf provides below language
"chartScrollbarSettings ChartScrollbar. If you change a property after the chart is initialized, you should call stockChart.validateNow() method in order for it to work. If there is no default value specified, default value of ChartScrollbar class will be used"
I would like to see the validateNow() method being triggered in an example. Usage of validateNow() and validateData() methods is probably the most important part of the package that I am missing today as I enter the final stages of my webapp development.
I have implemented it within an amChart "event" [panelRemoved event] using addListener.
The below works perfectly - I had two panels in my chart. I tried to change the chart type of the first panel stockGraph from line to column using the validateNow() method when user tries to close the second panel. I simple wanted to see if validateNow() method works and it does.
addListener('panelRemoved', 'function(event){ event.chart.panels[0].stockGraphs[0].type = "column"; event.chart.validateNow(); }')
But I really need to be able to call this method anytime based on R events and not just amCharts events. When I say R events, I am referring to say the click of an actionbutton within ui.R. Does the below work for you?
ui.R
actionbutton("samplebtn", label="Click Me"),
amChartsOutput("pic", type = NULL, width = "100%", height = "400px")
server.R
output$pic<-renderAmCharts({
stockChart<<-pipeR::pipeline( amSerialChart(dataDateFormat = 'YYYY',categoryField = 'year', startDuration = 0), setDataProvider(data.frame(year = 1990:2015, value = runif(length(1990:2015), -1, 1))), addValueAxes(axisAlpha = 0, position = 'left'), addGraph(id = 'g1', type = 'column', valueField = 'value', fillAlphas = 1), setCategoryAxis(minPeriod = 'YYYY', parseDates = TRUE), addListener('init', paste('function(event) {', 'setTimeout(function() {', ' event.chart.allLabels = [{', ' x: event.chart.marginLeftReal + 20,', ' y: event.chart.marginTopReal + 20,', ' text: "Watermark label",', ' size: 20,', ' color: "green",', ' alpha: 1', ' }];', ' event.chart.validateNow()', '}, 100)}')) )
return(plot(chart)) })
shinyjs::onclick("samplebtn", stockChart.validateNow())
Or you could Use
observeEvent(input$samplebtn,{
Change some chart property here
..... .....
Now validate the chart
stockChart.validateNow() })
Thank you for your cooperation and I am willing to bring ideas to the table,if needed, to implement it.
Thank you as always SD