modalDialog 在单击相同行后不会打开 reactable

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

modalDialog not opening after clicking on the same row in reactable

问题

我目前正在构建一个Shiny应用程序,用户可以在reactable中点击一行,并显示一个modalDialog,其中包含基于该行的更多信息。我遵循了这篇帖子(https://stackoverflow.com/questions/69593193/how-to-trigger-a-modalbox-with-observeevent-from-a-cell-rendered-button-in-a-rea)中的方法来获取onclick JavaScript函数。

然而,当我使用这个逻辑点击同一行时,没有任何反应。我必须在再次点击相同的行之前先点击另一行。我相信这是因为如果点击的是同一行,input$foo的值不会改变。

我尝试过在打开modalDialog时将input$foo设置为不同的值,但这也没有起作用。有谁知道如何解决这个问题或在打开后重置input$foo的值?我在JavaScript方面经验有限。下面是一个基本的Shiny示例,在单击特定行后,modalDialog的标题显示汽车名称。

library(shiny)
library(tidyverse)
library(reactable)

ui <- fluidPage(
  fluidRow(
    column(12, align = 'center', reactableOutput("tbl"))
  )
)

server <- function(input, output, session) {

  data = reactive({
    mtcars %>% add_rownames('car')
  })

  output$tbl = renderReactable(
    reactable(
      data(),
      defaultPageSize = 10,
      compact = T,
      highlight = T,
      defaultColDef = colDef(headerClass = "bar-sort-header",
                             sortNALast = T, align = 'center',
                             headerVAlign = 'center',
                             vAlign = 'center',
                             minWidth = 60
      ),
      onClick = JS("function(rowInfo, colInfo) {
                              Shiny.setInputValue('foo', rowInfo.id)
                            }"),
      rowStyle = list(cursor = "pointer")
    )
  )

  observeEvent(input$foo, {
    print(input$foo)
    showModal(
      modalDialog(
        size = 'l',
        easyClose = T,
        title = data()$car[as.numeric(input$foo)+1],
      )
    )
  })

}

shinyApp(ui = ui, server = server)
英文:

I am currently building a Shiny app where I'd allow a user to click on a row in a reactable and show a modalDialog with more info based on that row. I followed this post (https://stackoverflow.com/questions/69593193/how-to-trigger-a-modalbox-with-observeevent-from-a-cell-rendered-button-in-a-rea) to get the onclick JavaScript function.

However, when I click on the same row using this logic, nothing happens. I have to click on another row before I click back to that same row. I believe it's because input$foo does not change its value if the same row is being clicked.

I've tried setting input$foo to a different value when the modalDialog opens, but that has not been working either. Does anyone know how to work around this or reset that input$foo value after opening? I don't have a ton of experience in JavaScript. A basic Shiny example is shown below where the title of modalDialog displays the car name after clicking on the specific row.

library(shiny)
library(tidyverse)
library(reactable)

ui &lt;- fluidPage(
  fluidRow(
    column(12, align = &#39;center&#39;,reactableOutput(&quot;tbl&quot;))
    )
)


server &lt;- function(input, output, session) {
  
  data = reactive({
    mtcars %&gt;% add_rownames(&#39;car&#39;)
  })
  
  output$tbl = renderReactable(
    reactable(
      data(),
      defaultPageSize = 10,
      compact = T,
      highlight = T,
      defaultColDef = colDef(headerClass = &quot;bar-sort-header&quot;,
                             sortNALast = T, align = &#39;center&#39;,
                             headerVAlign = &#39;center&#39;,
                             vAlign = &#39;center&#39;,
                             minWidth = 60
      ),
      onClick = JS(&quot;function(rowInfo, colInfo) {
                              Shiny.setInputValue(&#39;foo&#39;, rowInfo.id)
                            }&quot;),
      rowStyle = list(cursor = &quot;pointer&quot;)
    )
  )
  
  observeEvent(input$foo, {
    print(input$foo)
    showModal(
      modalDialog(
        size = &#39;l&#39;,
        easyClose = T,
        title = data()$car[as.numeric(input$foo)+1],
      )
    )
  })
  
}

shinyApp(ui = ui, server = server)

答案1

得分: 3

以下是代码部分的翻译:

library(shiny)
library(tidyverse)
library(reactable)

ui &lt;- fluidPage(
  
  tags$head(
    tags$script(
    &quot;Shiny.addCustomMessageHandler(&#39;update_input_foo&#39;, function(value) {
      Shiny.setInputValue(&#39;foo&#39;, null)
    });
    &quot;)
  ),
  
  fluidRow(
    column(12, align = &#39;center&#39;,reactableOutput(&quot;tbl&quot;))
  )
)


server &lt;- function(input, output, session) {
  
  data = reactive({
    mtcars %&gt;% add_rownames(&#39;car&#39;)
  })
  
  output$tbl = renderReactable(
    reactable(
      data(),
      defaultPageSize = 10,
      compact = T,
      highlight = T,
      defaultColDef = colDef(headerClass = &quot;bar-sort-header&quot;,
                             sortNALast = T, align = &#39;center&#39;,
                             headerVAlign = &#39;center&#39;,
                             vAlign = &#39;center&#39;,
                             minWidth = 60
      ),
      onClick = JS(&quot;function(rowInfo, colInfo) {
                              Shiny.setInputValue(&#39;foo&#39;, rowInfo.id)
                            }&quot;),
      rowStyle = list(cursor = &quot;pointer&quot;)
    )
  )
  
  r &lt;- reactiveVal(NULL)
  
  observeEvent(input$foo, {
    
    if (!is.null(input$foo)) {
    showModal(
      modalDialog(
        size = &#39;l&#39;,
        easyClose = T,
        title = data()$car[as.numeric(input$foo)+1],
      )
    )
    
    session$sendCustomMessage(&quot;update_input_foo&quot;, 1)

    }
  })

}

shinyApp(ui = ui, server = server)
英文:

I also run into this problem a lot and my approach is to set the input$foo to null after calling showModal so we can click again on the same row:

library(shiny)
library(tidyverse)
library(reactable)

ui &lt;- fluidPage(
  
  tags$head(
    tags$script(
    &quot;Shiny.addCustomMessageHandler(&#39;update_input_foo&#39;, function(value) {
      Shiny.setInputValue(&#39;foo&#39;, null)
    });
    &quot;)
  ),
  
  fluidRow(
    column(12, align = &#39;center&#39;,reactableOutput(&quot;tbl&quot;))
  )
)


server &lt;- function(input, output, session) {
  
  data = reactive({
    mtcars %&gt;% add_rownames(&#39;car&#39;)
  })
  
  output$tbl = renderReactable(
    reactable(
      data(),
      defaultPageSize = 10,
      compact = T,
      highlight = T,
      defaultColDef = colDef(headerClass = &quot;bar-sort-header&quot;,
                             sortNALast = T, align = &#39;center&#39;,
                             headerVAlign = &#39;center&#39;,
                             vAlign = &#39;center&#39;,
                             minWidth = 60
      ),
      onClick = JS(&quot;function(rowInfo, colInfo) {
                              Shiny.setInputValue(&#39;foo&#39;, rowInfo.id)
                            }&quot;),
      rowStyle = list(cursor = &quot;pointer&quot;)
    )
  )
  
  r &lt;- reactiveVal(NULL)
  
  observeEvent(input$foo, {
    
    if (!is.null(input$foo)) {
    showModal(
      modalDialog(
        size = &#39;l&#39;,
        easyClose = T,
        title = data()$car[as.numeric(input$foo)+1],
      )
    )
    
    session$sendCustomMessage(&quot;update_input_foo&quot;, 1)

    }
  })

}

shinyApp(ui = ui, server = server)

答案2

得分: 2

以下是您要翻译的代码部分:

library(shiny)
library(tidyverse)
library(reactable)

ui <- fluidPage(
  fluidRow(
    column(12, align = 'center', reactableOutput("tbl"))
  )
)

server <- function(input, output, session) {

  data = reactive({
    mtcars %>% tibble::rownames_to_column('car')
  })

  output$tbl = renderReactable(
    reactable(
      data(),
      defaultPageSize = 10,
      compact = T,
      highlight = T,
      defaultColDef = colDef(headerClass = "bar-sort-header",
                             sortNALast = T, align = 'center',
                             headerVAlign = 'center',
                             vAlign = 'center',
                             minWidth = 60
      ),
      onClick = JS("function(rowInfo, colInfo) {
                              Shiny.setInputValue('foo', {id:rowInfo.id, nonce:Math.random()})
                             }"),
      rowStyle = list(cursor = "pointer")
    )
  )

  observeEvent(input$foo, {
    print(input$foo)

    id <- input$foo$id
    row_nr <- as.numeric(id) + 1

    showModal(
      modalDialog(
        size = 'l',
        easyClose = T,
        title = data()$car[row_nr]
      )
    )
  })

}

shinyApp(ui = ui, server = server)
英文:

I run into this problem a lot as well, here is a simpler approach with a random value sent each time when the row is clicked.

library(shiny)
library(tidyverse)
library(reactable)
ui &lt;- fluidPage(
fluidRow(
column(12, align = &#39;center&#39;,reactableOutput(&quot;tbl&quot;))
)
)
server &lt;- function(input, output, session) {
data = reactive({
mtcars %&gt;% tibble::rownames_to_column(&#39;car&#39;)
})
output$tbl = renderReactable(
reactable(
data(),
defaultPageSize = 10,
compact = T,
highlight = T,
defaultColDef = colDef(headerClass = &quot;bar-sort-header&quot;,
sortNALast = T, align = &#39;center&#39;,
headerVAlign = &#39;center&#39;,
vAlign = &#39;center&#39;,
minWidth = 60
),
onClick = JS(&quot;function(rowInfo, colInfo) {
Shiny.setInputValue(&#39;foo&#39;, {id:rowInfo.id, nonce:Math.random()})
}&quot;),
rowStyle = list(cursor = &quot;pointer&quot;)
)
)
observeEvent(input$foo, {
print(input$foo)
id &lt;- input$foo$id
row_nr &lt;- as.numeric(id)+1
showModal(
modalDialog(
size = &#39;l&#39;,
easyClose = T,
title = data()$car[row_nr],
)
)
})
}
shinyApp(ui = ui, server = server)

huangapple
  • 本文由 发表于 2023年2月23日 21:31:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545530.html
匿名

发表评论

匿名网友

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

确定