Skip to content
Advertisement

Shiny Custom Hoverable Dropdown

In my app I would like to have a custom html button as a dropdown menu. I want to have the selected option as an input$ variable. It shall then be printed to the console. With my code I am able to detect the click but instead of printing e.g. Link 1 it returns just an empty string.

library(shiny)

jscode <- '
$("#btn3").on("click", function(){
  Shiny.onInputChange("mydata", $("#btn3").text());
})
'


ui <- fluidPage(
  HTML( 
    '<style>
.dropbtn {
  background-color: #04AA6D;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
}

.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

.dropdown-content a:hover {background-color: #ddd;}

.dropdown:hover .dropdown-content {display: block;}

.dropdown:hover .dropbtn {background-color: #3e8e41;}
</style>


<div class="dropdown" id = "btn1">
  <button class="dropbtn" id = "btn2">Dropdown</button>
  <div id = "btn3" class="dropdown-content">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
</div>
         '), 

  singleton(tags$script(HTML(jscode)))
  
)

server = function(input, output, session) { 
  observeEvent(input$mydata, {
    
    print(paste("data is: ", input$mydata))
  })
}
runApp(list(ui = ui, server = server))

Advertisement

Answer

You can do

jscode <- '
$("a").on("click", function(){
  Shiny.onInputChange("mydata", $(this).text());
})
'

But this will also applies to other <a> tags in the app. So you can do instead

jscode <- '
$(".dropdown-content a").on("click", function(){
  Shiny.onInputChange("mydata", $(this).text());
})
'
Advertisement