两个条件面板并排 – 如果只有一个显示,如何让它们占满整行?

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

Shiny: Two conditional panels in a row - how to have them fill the entire row if only one is showing?

问题

我有一个包含两个条件面板的流体行。我想要这样做:如果只显示一个条件面板,它将占据整个行的宽度(宽度=12),而如果两者都显示,它们将平分空间(宽度=6)。

我尝试过使用多个基于逻辑的条件面板,根据一个或两个是否打开来判断,但最终显示了所有面板,而不考虑任何输入的值。

当我注释掉前两个条件面板或第三个条件面板中的一个时,逻辑就正常工作 - 因此不是单独的逻辑出了问题,而是在评估所有3个条件面板时出了问题。

那么,在这里我做错了什么吗?是否有更好的选择,而不是使用多个条件面板来实现相同的内容,比如一种方法,让它们自动占用所有可用的宽度?

fluidRow(
      conditionalPanel(condition = "input.chart_toggle && !input.table_toggle",
                       box(title = "Chart",
                           width = 12,
                           collapsible = F,
                           collapsed = F,
                           plotOutput("newplot")
                      )
      ),
      conditionalPanel(condition = "input.table_toggle && !input.chart_toggle",
                       box(title = "Table",
                           width = 12,
                           collapsible = F,
                           collapsed = F,
                           DTOutput("table")
                       )
      ),
      
      conditionalPanel(condition = "input.chart_toggle && input.table_toggle",
                       box(title = "Chart",
                           width = 6,
                           collapsible = F,
                           collapsed = F,
                           plotOutput("newplot")
                       ),
      
                       box(title = "Table",
                           width = 6,
                           collapsible = F,
                           collapsed = F,
                           DTOutput("table")
                       )
      )
)

两个条件面板并排 – 如果只有一个显示,如何让它们占满整行?
1: https://i.stack.imgur.com/r8gjR.png

英文:

I have a fluid row that contains two conditional panels. I would to make it so that if only one is being displayed, it takes up the entire row (width = 12), whereas if both are showing they both get equal space (width = 6).

I have attempted to use multiple conditional panels based on logic of whether one or both are turned on, but it ends up showing all of the panels regardless of the value of either of the inputs.

When I comment out either the first two conditional panels OR the 3rd one, the logic works fine - so it isn't the individual logic, it's something that isn't working when all 3 are evaluated.

So, is there something I'm doing wrong here? Is there a better option than having multiple conditional panels for the same content, such as a method for having them automatically take up as much width as is available?

fluidRow(
      conditionalPanel(condition = "input.chart_toggle && !input.table_toggle",
                       box(title = "Chart",
                           width = 12,
                           collapsible = F,
                           collapsed = F,
                           plotOutput("newplot")
                      )
      ),
      conditionalPanel(condition = "input.table_toggle && !input.chart_toggle",
                       box(title = "Table",
                           width = 12,
                           collapsible = F,
                           collapsed = F,
                           DTOutput("table")
                       )
      ),
      
      conditionalPanel(condition = "input.chart_toggle && input.table_toggle",
                       box(title = "Chart",
                           width = 6,
                           collapsible = F,
                           collapsed = F,
                           plotOutput("newplot")
                       ),
      
                       box(title = "Table",
                           width = 6,
                           collapsible = F,
                           collapsed = F,
                           DTOutput("table")
                       )
      )

两个条件面板并排 – 如果只有一个显示,如何让它们占满整行?

答案1

得分: 1

拥有多个相同的ID用于不同的输入/输出通常不是一个好主意。这很可能会导致意外行为。

话虽如此,使用conditionalPanel似乎会让事情变得有点复杂。

正如@Meisam在评论中所提到的,您可以使用renderUI,然后在那里设置条件。

另一种选择是使用{shinyjs}来隐藏和显示卡片,然后根据需要更新它们。

这里是一个演示:

global.R

library(shiny)

ui.R

ui <- bs4Dash::bs4DashPage(
  header = bs4Dash::dashboardHeader(),
  sidebar = bs4Dash::dashboardSidebar(),
  body = bs4Dash::dashboardBody(
    shinyjs::useShinyjs(),
    checkboxInput(
      inputId = "chart_toggle",
      label = "Show chart",
      value = TRUE
    ),
    checkboxInput(
      inputId = "table_toggle",
      label = "Show table",
      value = TRUE
    ),
    fluidRow(
      bs4Dash::bs4Card(
        id = "chart_card",
        title = "Chart",
        width = 6,
        collapsible = FALSE,
        plotOutput("newplot")
      ),
      bs4Dash::bs4Card(
        id = "table_card",
        title = "Table",
        width = 6,
        collapsible = FALSE,
        DT::DTOutput(outputId = "table")
      )
    )
  )
)

server.R

server <- function(input, output, session) {
  output$newplot <- renderPlot({
    plot(
      x = iris$Sepal.Length,
      y = iris$Petal.Width,
      col = iris$Species,
      xlab = "Sepal Length",
      ylab = "Petal Width",
      pch = 19
    )
  })
  
  output$table <- DT::renderDT({
    DT::datatable(
      iris,
      options = list(scrollX = TRUE)
    )
  })
  
  observeEvent(c(input$chart_toggle, input$table_toggle), {
    chart_toggle <- input$chart_toggle
    table_toggle <- input$table_toggle
    if (chart_toggle && !table_toggle) {
      shinyjs::hide(id = "table_card")
      bs4Dash::updatebs4Card(
        id = "chart_card",
        action = "update",
        options = list(width = 12)
      )
      shinyjs::show(id = "chart_card")
    }

    if (!chart_toggle && table_toggle) {
      shinyjs::hide(id = "chart_card")
      bs4Dash::updatebs4Card(
        id = "table_card",
        action = "update",
        options = list(width = 12)
      )
      shinyjs::show(id = "table_card")
    }

    if (chart_toggle && table_toggle) {
      bs4Dash::updatebs4Card(
        id = "chart_card",
        action = "update",
        options = list(width = 6)
      )
      bs4Dash::updatebs4Card(
        id = "table_card",
        action = "update",
        options = list(width = 6)
      )
      shinyjs::show(id = "chart_card")
      shinyjs::show(id = "table_card")
    }
    
    if (!chart_toggle && !table_toggle) {
      shinyjs::hide(id = "chart_card")
      shinyjs::hide(id = "table_card")
    }
  })
}
英文:

Having multiple identical ids for different inputs/outputs is never a good idea. It will most certainly result in unexpected behaviour.

That said, using conditionalPanel seems to complicate things a bit.

As @Meisam stated in the comments, you can use renderUI and then put the conditions there.

Another alternative would be to use {shinyjs} to hide and show the cards, and then update them as required.

Here is a reprex:

两个条件面板并排 – 如果只有一个显示,如何让它们占满整行?

global.R

library(shiny)

ui.R

ui &lt;- bs4Dash::bs4DashPage(
  header = bs4Dash::dashboardHeader(),
  sidebar = bs4Dash::dashboardSidebar(),
  body = bs4Dash::dashboardBody(
    shinyjs::useShinyjs(),
    checkboxInput(
      inputId = &quot;chart_toggle&quot;,
      label = &quot;Show chart&quot;,
      value = TRUE
    ),
    checkboxInput(
      inputId = &quot;table_toggle&quot;,
      label = &quot;Show table&quot;,
      value = TRUE
    ),
    fluidRow(
      bs4Dash::bs4Card(
        id = &quot;chart_card&quot;,
        title = &quot;Chart&quot;,
        width = 6,
        collapsible = FALSE,
        plotOutput(&quot;newplot&quot;)
      ),
      bs4Dash::bs4Card(
        id = &quot;table_card&quot;,
        title = &quot;Table&quot;,
        width = 6,
        collapsible = FALSE,
        DT::DTOutput(outputId = &quot;table&quot;)
      )
    )
  )
)

server.R

server &lt;- \(input, output, session) {
  output$newplot &lt;- renderPlot({
    plot(
      x = iris$Sepal.Length,
      y = iris$Petal.Width,
      col = iris$Species,
      xlab = &quot;Sepal Length&quot;,
      ylab = &quot;Petal Width&quot;,
      pch = 19
    )
  })
  
  output$table &lt;- DT::renderDT({
    DT::datatable(
      iris,
      options = list(scrollX = TRUE)
    )
  })
  
  observeEvent(c(input$chart_toggle, input$table_toggle), {
    chart_toggle &lt;- input$chart_toggle
    table_toggle &lt;- input$table_toggle
    if (chart_toggle &amp;&amp; !table_toggle) {
      shinyjs::hide(id = &quot;table_card&quot;)
      bs4Dash::updatebs4Card(
        id = &quot;chart_card&quot;,
        action = &quot;update&quot;,
        options = list(width = 12)
      )
      shinyjs::show(id = &quot;chart_card&quot;)
    }

    if (!chart_toggle &amp;&amp; table_toggle) {
      shinyjs::hide(id = &quot;chart_card&quot;)
      bs4Dash::updatebs4Card(
        id = &quot;table_card&quot;,
        action = &quot;update&quot;,
        options = list(width = 12)
      )
      shinyjs::show(id = &quot;table_card&quot;)
    }

    if (chart_toggle &amp;&amp; table_toggle) {
      bs4Dash::updatebs4Card(
        id = &quot;chart_card&quot;,
        action = &quot;update&quot;,
        options = list(width = 6)
      )
      bs4Dash::updatebs4Card(
        id = &quot;table_card&quot;,
        action = &quot;update&quot;,
        options = list(width = 6)
      )
      shinyjs::show(id = &quot;chart_card&quot;)
      shinyjs::show(id = &quot;table_card&quot;)
    }
    
    if (!chart_toggle &amp;&amp; !table_toggle) {
      shinyjs::hide(id = &quot;chart_card&quot;)
      shinyjs::hide(id = &quot;table_card&quot;)
    }
  })
}

huangapple
  • 本文由 发表于 2023年7月18日 04:36:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707916.html
匿名

发表评论

匿名网友

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

确定