英文:
Hot to use shinyjs to get the id of a clickable <div> element?
问题
以下是您要翻译的内容:
"I'm making a ShinyApp that uses plain HTML to order clickable <div>
sub-elements inside another <div>
element.
I want the click event on the sub-elements to trigger a reactiveVal()
in my server logic. I could do so by using shinyjs::onclick("<div>.id", reactiveVal(id))
, but I would appreciate a better way of using the .id
attribute of my sub<div>
to directly modify my reactiveVal()
, hopefully saving my from writing 118 onclick()
s...
Below is the MWE of what I tried so far:
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
fluidRow(
column(
2, offset = 1, h3('List of elements:'),
HTML(
'<div class = "periodic-table">
<div class = "element" style = "cursor: pointer;" id = "Hydrogen"> Hydrogen </div>
<div class = "element" style = "cursor: pointer;" id = "Helium"> Helium </div>
<div class = "element" style = "cursor: pointer;" id = "Lithium"> Lithium </div>
... <br> (115 more chemical elements)
</div>'
)
),
column(2, h3('Selected element:'), textOutput('SelectedElem'))
)
)
server <- function(input, output, session, devMode = TRUE) {
SelectedElem <- reactiveVal()
onclick("Hydrogen", SelectedElem("Hydrogen"))
onclick("Helium", SelectedElem("Helium"))
onclick("Lithium", SelectedElem("Lithium"))
output$SelectedElem <- renderText(SelectedElem())
}
shinyApp(ui = ui, server = server, enableBookmarking = "URL")
Desired behaviour:
英文:
I'm making a ShinyApp that uses plain HTML to order clickable <div>
sub-elements inside another <div>
element.
I want the click event on the sub-elements to trigger a reactiveVal()
in my server logic. I could do so by using shinyjs::onclick("<div>.id", reactiveVal(id))
, but I would appreciate a better way of using the .id
attribute of my sub<div>
to directly modify my reactiveVal()
, hopefully saving my from writting 118 onclick()
s...
Below is the MWE of what I tried so far:
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
fluidRow(
column(
2, offset = 1, h3('List of elements:'),
HTML(
'<div class = "periodic-table">
<div class = "element" style = "cursor: pointer;" id = "Hydrogen"> Hydrogen </div>
<div class = "element" style = "cursor: pointer;" id = "Helium"> Helium </div>
<div class = "element" style = "cursor: pointer;" id = "Lithium"> Lithium </div>
... <br> (115 more chemical elements)
</div>'
)
),
column(2, h3('Selected element:'), textOutput('SelectedElem'))
)
)
server <- function(input, output, session, devMode = TRUE) {
SelectedElem <- reactiveVal()
onclick("Hydrogen", SelectedElem("Hydrogen"))
onclick("Helium", SelectedElem("Helium"))
onclick("Lithium", SelectedElem("Lithium"))
output$SelectedElem <- renderText(SelectedElem())
}
shinyApp(ui = ui, server = server, enableBookmarking = "URL")
答案1
得分: 1
Essentially, what you want to do is add an event listener to each of these div
s that will update a common input. This can be accomplished with the javascript
function Shiny.onInputChange
(documentation).
There are multiple ways to add the event listener but this is one approach. In a separate file (in this case I'll use "www/sendID.js"):
$(document).ready(function() {
const elements = document.querySelectorAll('.element')
elements.forEach(element => {
element.addEventListener('click', () => Shiny.onInputChange("selected", element.id))
})
})
Then update your UI to include this script:
ui <- fluidPage(
useShinyjs(),
fluidRow(
column(
2, offset = 1, h3('List of elements:'),
HTML(
'<div class="periodic-table">
<div class="element" style="cursor: pointer;" id="Hydrogen"> Hydrogen </div>
<div class="element" style="cursor: pointer;" id="Helium"> Helium </div>
<div class="element" style="cursor: pointer;" id="Lithium"> Lithium </div>
... <br> (115 more chemical elements)
</div>'
)
),
column(2, h3('Selected element:'), textOutput('SelectedElem'))
),
includeScript("www/sendID.js")
)
Then in the server, you will only need to listen for a single input
:
server <- function(input, output, session, devMode = TRUE) {
output$SelectedElem <- renderText(input$selected)
}
英文:
Essentially, what you want to do is add an event listener to each of these div
s that will update a common input. This can be accomplished with the javascrip
function Shiny.onInputChange
(documentation).
There are multiple ways to add the event listener but this is one approach. In a separate file (in this case I'll use "www/sendID.js"):
$(document).ready(function() {
const elements = document.querySelectorAll('.element')
elements.forEach(element => {
element.addEventListener('click', () => Shiny.onInputChange("selected", element.id))
})
})
Then update your UI to include this script:
ui <- fluidPage(
useShinyjs(),
fluidRow(
column(
2, offset = 1, h3('List of elements:'),
HTML(
'<div class = "periodic-table">
<div class = "element" style = "cursor: pointer;" id = "Hydrogen"> Hydrogen </div>
<div class = "element" style = "cursor: pointer;" id = "Helium"> Helium </div>
<div class = "element" style = "cursor: pointer;" id = "Lithium"> Lithium </div>
... <br> (115 more chemical elements)
</div>'
)
),
column(2, h3('Selected element:'), textOutput('SelectedElem'))
),
includeScript("www/sendID.js")
)
Then in the server you will only need to listen for a single input
server <- function(input, output, session, devMode = TRUE) {
output$SelectedElem <- renderText(input$selected)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论