通过流数据更新防止选择输入重置

Posted

技术标签:

【中文标题】通过流数据更新防止选择输入重置【英文标题】:Prevent Select Input From Resetting With Streaming Data Updates 【发布时间】:2020-08-15 14:08:17 【问题描述】:

我试图想出一种方法来防止选择输入在其依赖的数据发生更改时重置。理想情况下,随着更多数据的到达,选择会悄悄地扩展,不会造成视觉中断或输入值重置。我试过使用updateSelectInput,但没有成功。我已经创建了一个合理地近似我的问题的示例,在我的 cmets 和想法中留下了我试图提出解决方案的地方,并希望其他人有更好的想法可以分享。与往常一样,提前感谢您。 -nate

library(shiny)

if (interactive()) 

ui <- fluidPage(

  titlePanel("Is It Possible To Prevent The Select Input From Resetting with New Data Arriving?"),


  sidebarLayout(
      sidebarPanel(
      shiny::uiOutput(outputId = "streaming_select")
    ),

    mainPanel(
    tableOutput("table")
    )
  )
)

server<- function(input, output, session)

  session_launched<- reactiveValues(count=1)
  fake_global_rv_list<- reactiveValues()
  fake_global_rv_list$tmp<- data.frame(glob_0001=runif(10))
  session_rv_list<- reactiveValues()
  session_rv_list$tmp<- data.frame(sess_0001=runif(10)) 

  # Simulating Streaming Data every 7 seconds
  shiny::observe(
    shiny::invalidateLater(millis = 7000)
    shiny::isolate(
      shiny::showNotification(ui = "Generating Random Data", type = "default", duration = 3)
      tmp<- data.frame(runif(10) )
      colnames(tmp)<- paste0("stream_",format(as.numeric(Sys.time())))
      session_rv_list$tmp<- cbind(session_rv_list$tmp,  tmp) # Put the random data into the reactive Values list
    ) 

  )

  full_dat<- shiny::reactive( cbind(fake_global_rv_list$tmp,  session_rv_list$tmp) )


  # Table of 'Streaming' Data 
  output$table <- renderTable(
    full_dat()
  )

  ## Select Input that let's you pick a single column
  output$streaming_select<- shiny::renderUI(
    if(!is.null(full_dat()))
      if(session_launched$count==1)
        out<- shiny::selectizeInput(inputId = "streaming_select_input", label="Pick A Column", choices = unique(colnames(full_dat())), selected = NULL, multiple = TRUE)
       
    
  )
  ## Possible Ideas (?) BELOW

  # select_choices<- shiny::eventReactive(full_dat(), 
  #   if(!is.null(full_dat()))
  #     if(session_launched$count==1)
  #       out<- list( choices = unique(colnames(full_dat())), selected = NULL)
  #       #shiny::selectizeInput(inputId = "streaming_select_input", label="Pick A Column", choices = unique(colnames(full_dat())), selected = NULL, multiple = TRUE)
  #       session_launched$count<- 2
  #       return(out)
  #      else if(session_launched$count > 1)
  #       old_selections<- input$streaming_select_input
  #       out<- list( choices = unique(colnames(full_dat())), selected = old_selections)
  #       return(out)
  #       #shiny::updateSelectizeInput(session, inputId = "streaming_select_input", choices = unique(colnames(full_dat())), selected = old_selections)
  #     
  #   
  # )
  # observeEvent(select_choices(), 
  #   cat("STR of select_choices is...", "\n")
  #   cat(str(select_choices()), "\n")
  # )
  # 

  # shiny::observeEvent(full_dat(), 
  #   if(session_launched$count != 1)
  #     old_selections<- input$streaming_select_input
  #     shiny::updateSelectizeInput(session, inputId = "streaming_select_input", choices = unique(colnames(full_dat())), selected = old_selections)
  #   
  # )




shinyApp(ui, server)


【问题讨论】:

恐怕没有简单的选择。查看 selectize.js 概述。可能你必须编写自己的 JS 函数来实现这个github.com/selectize/selectize.js/blob/master/docs/usage.md 【参考方案1】:

下面是一个有效的例子。我在ui 部分中创建了selectizeInput,并使用observeEvent 在更改full_dat 数据框时对其进行更新。我必须在此更新步骤中存储并重置选择,以防止将其设置为 NULL

library(shiny)

if (interactive()) 

  ui <- fluidPage(

    titlePanel("Is It Possible To Prevent The Select Input From Resetting with New Data Arriving?"),


    sidebarLayout(
      sidebarPanel(
        shiny::selectizeInput(inputId = "streaming_select_input", label="Pick A Column",
                               choices = NULL,
                               selected = NULL,
                               multiple = TRUE)
      ),

      mainPanel(
        tableOutput("table")
      )
    )
  )

  server<- function(input, output, session)

    session_launched<- reactiveValues(count=1)
    fake_global_rv_list<- reactiveValues()
    fake_global_rv_list$tmp<- data.frame(glob_0001=runif(10))
    session_rv_list<- reactiveValues()
    session_rv_list$tmp<- data.frame(sess_0001=runif(10)) 

    # Simulating Streaming Data every 7 seconds
    shiny::observe(
      shiny::invalidateLater(millis = 7000)
      shiny::isolate(
        shiny::showNotification(ui = "Generating Random Data", type = "default", duration = 3)
        tmp<- data.frame(runif(10) )
        colnames(tmp)<- paste0("stream_",format(as.numeric(Sys.time())))
        session_rv_list$tmp<- cbind(session_rv_list$tmp,  tmp) # Put the random data into the reactive Values list
      ) 

    )

    full_dat<- shiny::reactive( cbind(fake_global_rv_list$tmp,  session_rv_list$tmp) )


    # Table of 'Streaming' Data 
    output$table <- renderTable(
      full_dat()
    )

    ## Select Input that let's you pick a single column
    observeEvent(full_dat(), 
      selectedCols <- input$streaming_select_input
      updateSelectizeInput(session, "streaming_select_input", choices = colnames(full_dat()), selected = selectedCols)
    )
  

  shinyApp(ui, server)


【讨论】:

然而,当新数据到达时,是否仍然存在视觉中断。即,下拉选择消失,您需要再次单击? 有,你是对的。这个答案只解决了输入值的重置。 这个想法很有效。我对其进行了一些更改以适用于我的示例,但这让我走上了正确的道路。我刚刚了解到您可以在创建之前从input 列表中获取输入的值。奇怪,但非常有用。 @Bas,@mnist:谢谢你们。

以上是关于通过流数据更新防止选择输入重置的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 防止列表在项目选择时将滚动位置重置为顶部

防止多步 Formik 表单在重新渲染上一步时重置表单控件输入

UITableViewCell 内的 UITextField - 防止文本重置的方法

Drupal 6如何防止特定用户的自动密码恢复和重置

防止 AJAX 中的滚动重置

如何防止由于 blob 输入而导致流分析的值加倍