Jordan
Jordan

Reputation: 465

How to Disable Plot Clicking in R+Shiny

I have a plot that I want to be clickable until a button is clicked. shinyjs::disable does not appear to do the trick. Is there a way to do this.

Minimum Working Example

library(shiny)

## ui.R
ui <- fluidPage(
    shinyjs::useShinyjs(),
    column(12,
    plotOutput("Locations", width=500, height=500,
        click="plot_click"), inline=TRUE ),
    actionButton("stop", "Stop")
)


## server.R
server <- function( input, output, session){

    x <- reactiveValues(x=runif(10))
    y <- reactiveValues(y=rnorm(10))

    ## Click To Generate New Random Points
    observeEvent(input$plot_click, {
        x$x <- runif(10)
        y$y <- rnorm(10)
    })

    ## Disable Clicking
    observeEvent(input$stop, {
        shinyjs::disable("plot_click")
    })    

    ## Render Plot
    output$Locations <- renderPlot({ 

        ## Constant
        par(bg=NA)

        plot.new()
        plot.window(
            xlim=c(0,1), ylim=c(0,1),
            yaxs="i", xaxs="i")
        axis(1)
        axis(2)
        grid(10,10, col="black")
        box()

        ## Updating
        points( x$x, y$y, cex=3, pch=16)

    })        
}

### Run Application
shinyApp(ui, server)

Upvotes: 2

Views: 571

Answers (1)

RmIu
RmIu

Reputation: 4477

There's a couple of ways to do this. You can prevent the logic in server.R from triggering the render of a new plot:

Option 1.

## server.R
server <- function( input, output, session){

  x <- reactiveValues(x=runif(10))
  y <- reactiveValues(y=rnorm(10))

  disabled <- FALSE

  ## Click To Generate New Random Points
  observeEvent(input$plot_click, {
    if(disabled) return()
    x$x <- runif(10)
    y$y <- rnorm(10)
  })

  ## Disable Clicking
  observeEvent(input$stop, {
    disabled <<- TRUE
  })    

  ## Render Plot
  output$Locations <- renderPlot({ 
    # Create plot
  })        
}

Option 2. (jQuery)

Or you could unbind the click event using jQuery as:

## ui.R
ui <- fluidPage(
  tags$head(
    tags$script(
      HTML("
            Shiny.addCustomMessageHandler ('disablePlotClick',function (message) {
              $('#'+message.ID).unbind();
            });")
    )
  ),
  column(12,
         plotOutput("Locations", width=500, height=500,
                    click="plot_click"), inline=TRUE ),
  actionButton("stop", "Stop")
)

Define a function to call the Javascript function:

disablePlotClick <- function(session, id){
  session$sendCustomMessage(type = 'disablePlotClick', message = c("ID"=id))
}

And then simply call the function when you want to disable the click event:

## Disable Clicking
  observeEvent(input$stop, {
    disablePlotClick(session, 'Locations')
  })  

Option 2. (shinyjs)

This can also be done using shinyjs as:

jsCode <- "shinyjs.disablePlotClick = function(ID){ $('#'+ID).unbind(); console.log(ID);}"

## ui.R
ui <- fluidPage(
  shinyjs::useShinyjs(),
  shinyjs::extendShinyjs(text = jsCode, functions=c("disablePlotClick")),

  # More UI code
)

And call the function:

## Disable Clicking
  observeEvent(input$stop, {
    js$disablePlotClick("Locations")
  }) 

Upvotes: 2

Related Questions