如何使用shinyjs获取可点击的
元素的ID?

huangapple go评论65阅读模式
英文:

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("&lt;div&gt;.id", reactiveVal(id)), but I would appreciate a better way of using the .id attribute of my sub&lt;div&gt; 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:

如何使用shinyjs获取可点击的<div>元素的ID?

英文:

I'm making a ShinyApp that uses plain HTML to order clickable &lt;div&gt; sub-elements inside another &lt;div&gt; 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(&quot;&lt;div&gt;.id&quot;, reactiveVal(id)), but I would appreciate a better way of using the .id attribute of my sub&lt;div&gt; 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 &lt;- fluidPage(
  useShinyjs(),
  fluidRow(
    column(
      2, offset = 1, h3(&#39;List of elements:&#39;),
      HTML(
        &#39;&lt;div class = &quot;periodic-table&quot;&gt;
            &lt;div class = &quot;element&quot; style = &quot;cursor: pointer;&quot; id = &quot;Hydrogen&quot;&gt; Hydrogen &lt;/div&gt;
            &lt;div class = &quot;element&quot; style = &quot;cursor: pointer;&quot; id = &quot;Helium&quot;&gt; Helium &lt;/div&gt;
            &lt;div class = &quot;element&quot; style = &quot;cursor: pointer;&quot; id = &quot;Lithium&quot;&gt; Lithium &lt;/div&gt;
            ... &lt;br&gt; (115 more chemical elements)
         &lt;/div&gt;&#39;
      )
    ),
    column(2, h3(&#39;Selected element:&#39;), textOutput(&#39;SelectedElem&#39;))
  )
)

server &lt;- function(input, output, session, devMode = TRUE) {
  SelectedElem &lt;- reactiveVal()
  
  onclick(&quot;Hydrogen&quot;, SelectedElem(&quot;Hydrogen&quot;))
  onclick(&quot;Helium&quot;, SelectedElem(&quot;Helium&quot;))
  onclick(&quot;Lithium&quot;, SelectedElem(&quot;Lithium&quot;))
  
  output$SelectedElem &lt;- renderText(SelectedElem())
}

shinyApp(ui = ui, server = server, enableBookmarking = &quot;URL&quot;)

Desired behaviour:
> 如何使用shinyjs获取可点击的<div>元素的ID?

答案1

得分: 1

Essentially, what you want to do is add an event listener to each of these divs 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 divs 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(&#39;.element&#39;)
  
  elements.forEach(element =&gt; {
    element.addEventListener(&#39;click&#39;, () =&gt; Shiny.onInputChange(&quot;selected&quot;, element.id))
  })
  
})

Then update your UI to include this script:

ui &lt;- fluidPage(
  useShinyjs(),
  fluidRow(
    column(
      2, offset = 1, h3(&#39;List of elements:&#39;),
      HTML(
        &#39;&lt;div class = &quot;periodic-table&quot;&gt;
            &lt;div class = &quot;element&quot; style = &quot;cursor: pointer;&quot; id = &quot;Hydrogen&quot;&gt; Hydrogen &lt;/div&gt;
            &lt;div class = &quot;element&quot; style = &quot;cursor: pointer;&quot; id = &quot;Helium&quot;&gt; Helium &lt;/div&gt;
            &lt;div class = &quot;element&quot; style = &quot;cursor: pointer;&quot; id = &quot;Lithium&quot;&gt; Lithium &lt;/div&gt;
            ... &lt;br&gt; (115 more chemical elements)
         &lt;/div&gt;&#39;
      )
    ),
    column(2, h3(&#39;Selected element:&#39;), textOutput(&#39;SelectedElem&#39;))
  ),
  includeScript(&quot;www/sendID.js&quot;)
)

Then in the server you will only need to listen for a single input

server &lt;- function(input, output, session, devMode = TRUE) {  
  output$SelectedElem &lt;- renderText(input$selected)
}

huangapple
  • 本文由 发表于 2023年2月18日 01:13:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75487336.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定