problème0123
problème0123

Reputation: 871

avoid ObserveEvent from launching itself several times when the application is launched

I have a button that when you click on it, it displays a table and when you click on a line, it displays the line number in a verbatimTextOutput

I have a reactive variable o() that saves all the lines that have been selected and when no line is selected it displays "nothing".

When I launch the application it displays several times "nothing" I don't understand why.

How could I redo the code to avoid these multiple appearances when launching the application?

library(shiny)

ui <- fluidPage(
  DT::dataTableOutput("table"),
  verbatimTextOutput("output", placeholder = TRUE),
  actionButton("updateTable", "Show data table")
)

server <- function(input, output) {

  dt <- reactiveVal()
  o <- reactiveVal()

  val <- reactive(
    tail(
      as.character(dt()[input$table_rows_selected, 2]),
      n=1)
  )

  val2 <- reactiveVal()    

  observeEvent(input$updateTable, {
    # the datatable
    dt(data.frame("a" = paste("a", 1:10), "b" = paste("b", 1:10)))
    output$table <- DT::renderDataTable({
      DT::datatable(dt(), selection = list(target = 'row'))
    })
    if(is.null(val())){ val2("nothing")}
  })

  observeEvent(val(), {
    if(length(input$table_rows_selected) > 0){
      val2(val())
      o(c(o(), "\n", "You chose :", val2()))
    } else{
      val2("nothing")
      o(c(o(), "\n", "You chose :", val2()))
    }
    output$output <- renderText({ o() })
  })
}

shinyApp(ui = ui, server = server)

solution 1

library(shiny)

ui <- fluidPage(
  DT::dataTableOutput("table"),
  verbatimTextOutput("output", placeholder = TRUE),
  actionButton("showTable", "Show data table")
)

server <- function(input, output) {

  val <- reactiveVal()
  o   <- reactiveVal()
  dt  <- reactiveVal()

  observe({
    val(as.character(dt()[input$table_rows_selected, 2]))
  })


  observeEvent(input$showTable, {
    dt(data.frame("a" = paste("a", 1:10), "b" = paste("b", 1:10)))
    output$table <- DT::renderDataTable({
      DT::datatable(dt(), selection = list(target = 'row'))
    })
    o(c(o(), "\n", "Display of the table"))
  })


  output$output <- renderText({
    if(input$showTable)
    {
      if(!identical(val(), character(0))){
        o(c( isolate(o()), "\n", "You chose: ", isolate(val())))
      } else{
        o(c( isolate(o()), "\n", "You chose: ", "nothing"))
      }
      o()
    }
  })
}

shinyApp(ui = ui, server = server)

Solution 2

library(shiny)

ui <- fluidPage(
  DT::dataTableOutput("table"),
  verbatimTextOutput("output", placeholder = TRUE),
  actionButton("showTable", "Show data table")
)

server <- function(input, output) {

  o   <- reactiveVal()
  dt  <- reactiveVal()

  observeEvent(input$showTable, {
    dt(data.frame("a" = paste("a", 1:10), "b" = paste("b", 1:10)))
    output$table <- DT::renderDataTable({
      DT::datatable(dt(), selection = list(target = 'row'))
    })
    o(c(o(), "\n", "Display of the table"))
  })

  val <- reactive({
    if(!is.null(input$table_rows_selected)){
      tail(
        as.character(dt()[input$table_rows_selected, 2]),
        n = 1
      )
    } else{ "nothing" }
  })

  observeEvent(val(), {
    if(input$showTable)
    {
      o(c(o(), "\n", "You chose: ", val()))
    }

  })

  output$output <- renderText({ o() })
}

shinyApp(ui = ui, server = server)

Upvotes: 0

Views: 142

Answers (2)

Kevin
Kevin

Reputation: 2044

It's due to your reactive values updating when the table is shown. The easiest solution is just remove adding "\n", "You chose :", val2() to your list and just have it as a default option for o().

See below for the code:

library(shiny)

ui <- fluidPage(
  DT::dataTableOutput("table"),
  verbatimTextOutput("output", placeholder = TRUE),
  actionButton("updateTable", "Show data table")
)

server <- function(input, output) {

  dt <- reactiveVal()
  o <- reactiveVal()

  val <- reactive(
    tail(
      as.character(dt()[input$table_rows_selected, 2]),
      n=1)
  )

  val2 <- reactiveVal()    

  observeEvent(input$updateTable, {
    # the datatable
    dt(data.frame("a" = paste("a", 1:10), "b" = paste("b", 1:10)))
    output$table <- DT::renderDataTable({
      DT::datatable(dt(), selection = list(target = 'row'))
    })
    if(is.null(val())){ val2("nothing")}
  })

  observeEvent(val(), {
    if(length(input$table_rows_selected) > 0){
      val2(val())
      o(c(o(), "\n", "You chose :", val2()))
    } else{
      val2("nothing")
      o(c("\n", "You chose :", val2()))
    }
    output$output <- renderText({ o() })
  })
}

shinyApp(ui = ui, server = server)

UPDATED

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  DT::dataTableOutput("table"),
  verbatimTextOutput("output", placeholder = TRUE),
  actionButton("updateTable", "Show data table")
)

server <- function(input, output) {

  #Data table
  dt <- data.frame("a" = paste("a", 1:10), "b" = paste("b", 1:10))

  output$table <- DT::renderDataTable({
    DT::datatable(dt, selection = list(target = 'row'))
  })

  shinyjs::hide("table")


  #Button
  observeEvent(input$updateTable, {
    shinyjs::show("table")
    shinyjs::show("output")
  })


  #Value Box
  o <- reactiveVal()

  val <- reactive({
    tail(
      as.character(dt[input$table_rows_selected, 2]), 
      n = 1
    )
  })

  observeEvent(val(), {
      if(length(input$table_rows_selected) > 0){
        o(c(o(), "\n", "You chose :", val()))
      } else{
        req(o())
        o(c(o(), "\n", "You chose : nothing"))
      }
  })

  output$output <- renderText({ o() })
  shinyjs::hide("output")
}

shinyApp(ui = ui, server = server)

Upvotes: 1

Shree
Shree

Reputation: 11140

Your approach is too complex. Here's a simplified way -

library(shiny)

ui <- fluidPage(
  DT::dataTableOutput("table"),
  verbatimTextOutput("output", placeholder = TRUE),
  actionButton("updateTable", "Show data table")
)

server <- function(input, output) {

  val <- reactiveVal()

  dt <- eventReactive(input$updateTable, {
    # the datatable
    data.frame("a" = paste("a", 1:10), "b" = paste("b", 1:10))
  })

  output$table <- DT::renderDataTable({
      DT::datatable(dt(), selection = list(target = 'row'))
  })

  observe({
    val(c(isolate(val()), as.character(dt()[input$table_rows_selected, 2])))
  })

  output$output <- renderText({ paste0("\n You chose :", unique(val())) })
}

shinyApp(ui = ui, server = server)

enter image description here

Upvotes: 1

Related Questions