简体   繁体   English

只有在第二次单击后,Highcharter剧情才会更新-R Shiny

[英]Highcharter plot updates only after second click - R Shiny

This is my Code, similar like the question I already posted today. 这是我的代码,类似于我今天已经发布的问题。 Now I have another issue I can not get my head around. 现在我有另一个问题,我无法解决。 When I click the actionButton to update the chart, the chart only updates after the second click. 当我单击actionButton更新图表时,图表仅在第二次单击后更新。 The print statement works after the first click. 第一次单击后, print语句生效。 What is going wrong here? 这是怎么了?

library(highcharter)
library(shiny)
library(shinyjs)

df <- data.frame(
    a = floor(runif(10, min = 1, max = 10)),
    b = floor(runif(10, min = 1, max = 10))
)


updaterfunction <- function(chartid, sendid, df, session) {

    message = jsonlite::toJSON(df)
    session$sendCustomMessage(sendid, message)

    jscode <- paste0('Shiny.addCustomMessageHandler("', sendid, '", function(message) {
        var chart1 = $("', chartid, '").highcharts()

        var newArray1 = new Array(message.length)
        var newArray2 = new Array(message.length)

        for(var i in message) {
            newArray1[i] = message[i].a
            newArray2[i] = message[i].b
        }

        chart1.series[0].update({
            // type: "line",
            data: newArray1
        }, false)

        chart1.series[1].update({
        //   type: "line",
          data: newArray2
      }, false)

      console.log("code was run")

      chart1.redraw();
    })')

    print("execute code!")
    runjs(jscode)
}




# Define UI for application that draws a histogram
ui <- fluidPage(

    # Application title
    titlePanel("Update highcharter dynamically"),
    #includeScript("www/script.js"),
    useShinyjs(),

    # Sidebar with a slider input for number of bins 
    sidebarLayout(
        sidebarPanel(
            actionButton("data", "Generate Data")
        ),

        # Show a plot of the generated distribution
        mainPanel(
           highchartOutput("plot")
        )
    )
)


server <- function(input, output, session) {


    observeEvent(input$data, {

        df1 <- data.frame(
            a = floor(runif(10, min = 1, max = 10)),
            b = floor(runif(10, min = 1, max = 10))
        )

        updaterfunction(chartid = "#plot", sendid = "handler", df = df1, session = session)

    })


    output$plot <- renderHighchart({

        highchart() %>%

            hc_add_series(type = "bar", data = df$a) %>%
            hc_add_series(type = "bar", data = df$b)

    })
}

# Run the application 
shinyApp(ui = ui, server = server)

Just Add ignoreNULL=FALSE in observeEvent function- 只需在observeEvent函数中添加ignoreNULL=FALSE observeEvent

I noticed @ismirsehregal mentioned this trick in the comments. 我注意到@ismirsehregal在评论中提到了这个技巧。

Working Code- 工作守则

library(highcharter)
library(shiny)
library(shinyjs)

df <- data.frame(
  a = floor(runif(10, min = 1, max = 10)),
  b = floor(runif(10, min = 1, max = 10))
)


updaterfunction <- function(chartid, sendid, df, session) {

  message = jsonlite::toJSON(df)
  session$sendCustomMessage(sendid, message)

  jscode <- paste0('Shiny.addCustomMessageHandler("', sendid, '", function(message) {
        var chart1 = $("', chartid, '").highcharts()

        var newArray1 = new Array(message.length)
        var newArray2 = new Array(message.length)

        for(var i in message) {
            newArray1[i] = message[i].a
            newArray2[i] = message[i].b
        }

        chart1.series[0].update({
            // type: "line",
            data: newArray1
        }, false)

        chart1.series[1].update({
        //   type: "line",
          data: newArray2
      }, false)

      console.log("code was run")

      chart1.redraw();
    })')

  print("execute code!")
  runjs(jscode)
}




# Define UI for application that draws a histogram
ui <- fluidPage(

  # Application title
  titlePanel("Update highcharter dynamically"),
  #includeScript("www/script.js"),
  useShinyjs(),

  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      actionButton("data", "Generate Data")
    ),

    # Show a plot of the generated distribution
    mainPanel(
      highchartOutput("plot")
    )
  )
)


server <- function(input, output, session) {


  observeEvent(input$data, ignoreNULL = FALSE, {

    df1 <- data.frame(
      a = floor(runif(10, min = 1, max = 10)),
      b = floor(runif(10, min = 1, max = 10))
    )
    print(df1)
    updaterfunction(chartid = "#plot", sendid = "handler", df = df1, session = session)

  })


  output$plot <- renderHighchart({

    highchart() %>%

      hc_add_series(type = "bar", data = df$a) %>%
      hc_add_series(type = "bar", data = df$b)

  })
}

# Run the application 
shinyApp(ui = ui, server = server)

I guess the problem is, that you are attaching the event handler for your plot after observeEvent(input$data, {...}) is executed for the first time (actually you are adding a the CustomMessageHandler after every button click). 我想问题是,您是在第一次执行observeEvent(input$data, {...})之后observeEvent(input$data, {...})为情节添加事件处理程序的(实际上,您每次单击按钮后都会添加一个CustomMessageHandler)。 Accordingly the event handler isn't already attached during the first button click (and can't react). 因此,在第一次单击按钮期间事件处理程序尚未附加(并且无法做出反应)。

If you initialize the CustomMessageHandler once on session-startup and only send new messages on a button click it works as expected: 如果您在会话启动时一次初始化CustomMessageHandler并仅在按钮上发送新消息,请单击它,按预期进行:

library(highcharter)
library(shiny)
library(shinyjs)

df <- data.frame(
  a = floor(runif(10, min = 1, max = 10)),
  b = floor(runif(10, min = 1, max = 10))
)

updaterfunction <- function(sendid, df, session) {
  message = jsonlite::toJSON(df)
  session$sendCustomMessage(sendid, message)
}

# Define UI for application that draws a histogram
ui <- fluidPage(

  # Application title
  titlePanel("Update highcharter dynamically"),
  #includeScript("www/script.js"),
  useShinyjs(),

  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      actionButton("data", "Generate Data")
    ),

    # Show a plot of the generated distribution
    mainPanel(
      highchartOutput("plot")
    )
  )
)


server <- function(input, output, session) {

  sendid <- "handler"
  chartid <- "#plot"

  jscode <- paste0('Shiny.addCustomMessageHandler("', sendid, '", function(message) {
        var chart1 = $("', chartid, '").highcharts()

        var newArray1 = new Array(message.length)
        var newArray2 = new Array(message.length)

        for(var i in message) {
            newArray1[i] = message[i].a
            newArray2[i] = message[i].b
        }

        chart1.series[0].update({
            // type: "line",
            data: newArray1
        }, false)

        chart1.series[1].update({
        //   type: "line",
          data: newArray2
      }, false)

      console.log("code was run")

      chart1.redraw();
    })')

  runjs(jscode)


  observeEvent(input$data, {

    df1 <- data.frame(
      a = floor(runif(10, min = 1, max = 10)),
      b = floor(runif(10, min = 1, max = 10))
    )

    updaterfunction(sendid = sendid, df = df1, session = session)

  })


  output$plot <- renderHighchart({

    highchart() %>%

      hc_add_series(type = "bar", data = df$a) %>%
      hc_add_series(type = "bar", data = df$b)

  })
}

# Run the application 
shinyApp(ui = ui, server = server)

In the end that's also what ignoreNULL = FALSE does: It attaches the CustomMessageHandler during session-startup. 最后,这也是ignoreNULL = FALSE作用:它在会话启动期间附加CustomMessageHandler

Please also check this useful article 请同时查看此有用的文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM