Confused by scoping rules


#1

Hi all,

Apologies if this question was previously answered, but I am a shiny new-bie! :wink:

I am using a shiny.app to sync a plot and a table display of a single record from a dataset in the global environment. I tried this:

# Define server logic ----
server <- function(input, output) {
  
  RecordPointer <- 1

  observeEvent(input$Next, {
    RecordPointer <- RecordPointer+1
  })
  
  observeEvent(input$Prev, {
    if(RecordPointer > 2) RecordPointer <- RecordPointer - 1
  })
  
  output$table <- DT::renderDataTable(DT::datatable(Discordant[RecordPointer,],
    options = list(pageLength = 1))
  )
  
  output$plot <- renderPlot({
    i <- RecordPointer
  })

[snip]
}

but the record displayed and plotted stays the same no matter how many times I hit next or prev…

I will greatly appreciate any hint that helps me see the error in my ways!

Alternatively, I will also appreciate if someone can help me how to access the “current” record in the DT, that way I will not have to construct my own navigator.

Thanks!!!
Jose


#2

To access which record is currently selected in DT you can use input$tableId_rows_selected. See more details here: https://rstudio.github.io/DT/shiny.html


#3

explained in first observer but same logic applies to the rest.

server <- function(input, output) {

  RecordPointer <- 1 #created in serverFunction environment, additionally i recommend using 1L as it assigns integer

  observeEvent(input$Next, {
    RecordPointer <- RecordPointer+1 #RecordPointer created inside observerEvent environment
    # value assigned from RecordPointer in serverFunction environment as RecordPointer inside current environment 
    # doesnt exist yet
    # RecordPointer from this environment gets deleted when function call ends
    # to change value in serverFunction use:
    assign(x = 'RecordPointer',value = RecordPointer+1L , envir = parent.env(environment()))
  })
}

#4

To modify a variable in the parent environment, it’s easier to just use <<- rather than assign. But in this case I wouldn’t even do that; since RecordPointer is just a normal variable it will not trigger reactivity.

Instead, use a reactiveVal:

function(input, output, session) {
  RecordPointer <- reactiveVal()

  observeEvent(input$Next, {
    RecordPointer(RecordPointer() + 1)
  }

  output$plot <- renderPlot({
    i <- RecordPointer()
    ...
  })
}

#5

Thank you all!

These explanations clear the fog I had regarding the scope of the server
function and the event handler functions.

I also appreciate the intro to reactive functions. That explains that when
I tried using <<- to increase the record counter in the event handler it
did not work either.

Thanks again!
Jose