过滤器不响应我闪亮的应用程序中的应用和清除按钮

Posted

技术标签:

【中文标题】过滤器不响应我闪亮的应用程序中的应用和清除按钮【英文标题】:filter does not respond to apply and clear buttons in my shiny app 【发布时间】:2021-02-26 09:04:48 【问题描述】:

我正在构建一个闪亮的应用程序以在地图上可视化酒店(使用传单包)。我有一个可以加载数据子集的下拉列表。除此之外,我还想在左上角建一个过滤按钮,可以用来进一步按年份过滤数据。

我希望过滤器仅在我单击 apply 按钮时响应。另外,我想在单击clear 按钮后清除过滤器。

下面是我闪亮的应用代码。我的applyclear 按钮似乎不起作用。一旦我从过滤器下拉列表中选择一年,我的地图就会刷新。我希望它仅在单击 apply 按钮后刷新。过滤器也不响应“清除”。我花了几个小时,但无法弄清楚为什么。有谁知道我做错了什么。

这是一个非常简化的版本。我的实际应用程序要复杂得多。在下拉按钮中有多个过滤器。

library(shiny)
library(leaflet)
library(shinyjs)
library(shinyWidgets)
library(dplyr)


df <- read.table(text = "Name Year Value longitude  latitude
                         A   2020  12    -106.50645 35.06745
                         B   2020  33    -116.00994 36.21834
                         C   2020  44    -115.24685 36.29460
                         A   2019  55    -115.24685 35.06745
                         B   2019  22    -118.18642 33.98881
                         C   2019  11    -111.83064 35.06745", 
                     header = TRUE)


ui <- fluidPage(
    
    selectizeInput(inputId = 'hotel', label='Hotel Type:',
                   choices = c('A', 'B', 'C'),
                   multiple=TRUE,
                   options = list(
                       maxItems = 1,
                       placeholder = '',
                       onInitialize = I("function()  this.setValue(''); "))),
    actionButton("load", "load"),
    
    
    div(id = 'map_filter',
        dropdown(
            tags$h3("Filters"),
            selectizeInput(inputId = 'year', label='Choose Year:',
                           choices = c(2020,2019),
                           multiple=TRUE,
                           options = list(
                               maxItems = 2,
                               placeholder = '',
                               onInitialize = I("function()  this.setValue(''); "))),
            #uiOutput('map_zipcode_prod2ui') ,
            # column(width=1, offset = 1, actionButton(inputId='map_zipcode_applyProductFilter',
            #                                          label='Apply Filter', style = 'margin-top:25px') )
            actionBttn(
                inputId = 'applyFilter',
                label = "Apply",
                style = "gradient",
                color = "danger",
                icon = icon("") ) ,
            actionBttn(
                inputId = 'clearFilter',
                label = "Clear",
                style = "gradient",
                color = "danger",
                icon = icon("") ) ,
            style = "unite", icon = icon("filter"),
            status = "danger", width = "300px"
        )  #dropdown
    ), #div
    
    
    leafletOutput("mymap")
    
)

server <- function(input, output, session) 
    
    df1 = eventReactive (input$load, 
        
        df %>% filter(Name == input$hotel)
    )
    
    df2 = reactive(
        if (length(input$year)==0) 
            df2 = df1()
         else 
            df2 = df1() %>% filter(Year %in% input$year)
        
    )
    
    # clear all filters
    observeEvent(input$clearFilter, 
        reset("map_filter")
    )
    
    
    observeEvent(c(input$load,input$applyFilter), ignoreInit = T, ignoreNULL = T, 
        
        output$mymap <- renderLeaflet(
            map <- leaflet()  %>%
                addProviderTiles("OpenStreetMap.Mapnik") %>% 
                addCircleMarkers( data = df2(),
                                  #group = 'Data Markers 1',
                                  lng = ~longitude,
                                  lat = ~latitude,
                                  radius = 10,
                                  stroke = F,
                                  fillOpacity = 0.9,
                                  color = 'red')
            
        )
    )


shinyApp(ui, server)

【问题讨论】:

【参考方案1】:

这是一种方法 - 希望对您有所帮助。

您可以将地图存储在reactiveVal 中。然后,您使用加载或应用过滤器按钮更新地图。否则,地图不会改变。

会考虑使用updateSelectizeInput 来清除您的过滤器。

编辑:根据评论,df1df2 没有合并。

server <- function(input, output, session) 

  map <- reactiveVal(NULL)

  df1 = reactive(
    req(input$hotel)
    filter(df, Name == input$hotel)
  )
  
  df2 = reactive(
    if (length(input$year)==0) 
      df2 = df1()
     else 
      df2 = df1() %>% filter(Year %in% input$year)
    
  )

  # clear all filters
  observeEvent(input$clearFilter, 
    updateSelectizeInput(session, inputId = 'year', selected = "")
  )

  output$mymap <- renderLeaflet(
    map()
  )

  observeEvent(c(input$load, input$applyFilter), ignoreInit = T, ignoreNULL = T, 
    map(leaflet()  %>%
      addProviderTiles("OpenStreetMap.Mapnik") %>%
      addCircleMarkers( data = df2(),
                        #group = 'Data Markers 1',
                        lng = ~longitude,
                        lat = ~latitude,
                        radius = 10,
                        stroke = F,
                        fillOpacity = 0.9,
                        color = 'red')
    )
  )


【讨论】:

@Ben 非常感谢提供这种工作方法。你能帮我弄清楚我在我的例子中做错了什么吗?为什么在我点击apply之前地图会刷新?我也想保留df2,因为它实际上是在应用程序的其他部分调用的。 你的map(leaflet()) 中有df2() - 并且df2()reactive 依赖于input$year - 所以如果input$year 发生变化,df2() 被调用并得到更新,并且map 也会更新。为避免这种情况,您可以将isolate 包装起来,例如data = isolate(df2()),然后如果df2() 发生更改,则不会重绘地图... @zesla 查看编辑后的答案 - 现在df2 留在里面。另外,我会将output 保留在observeEvent 过程之外并保持独立(如我的示例中所示)。跨度> 【参考方案2】:

试试这个

server <- function(input, output, session) 
  
  df1 = eventReactive (input$load, 
    df %>% filter(Name == req(input$hotel))
  )
  
  df2 = reactive(
    req(input$year)
    if (length(input$year)==0) 
      df2 = df1()
     else 
      df2 = df1() %>% filter(Year %in% input$year)
    
  )
  
  # clear all filters
  observeEvent(input$clearFilter, 
    output$mymap <- renderLeaflet(
      return(NULL)
    )
    #reset("map_filter")
  )
  
  
  observeEvent(input$applyFilter, ignoreInit = T, ignoreNULL = T, 
    req(input$load,df2())
    output$mymap <- renderLeaflet(
      map <- leaflet()  %>%
        addProviderTiles("OpenStreetMap.Mapnik") %>% 
        addCircleMarkers( data = df2(),
                          #group = 'Data Markers 1',
                          lng = ~longitude,
                          lat = ~latitude,
                          radius = 10,
                          stroke = F,
                          fillOpacity = 0.9,
                          color = 'red')
      
    )
  )


shinyApp(ui, server)

【讨论】:

地图在点击apply之前仍然会刷新。我还想在load 之后显示地图。使用下拉框进一步修改地图。 那么你的 observeEvent 就好了。另外,Ben 的回答很棒!

以上是关于过滤器不响应我闪亮的应用程序中的应用和清除按钮的主要内容,如果未能解决你的问题,请参考以下文章

闪亮的应用程序:禁用下载按钮

调整/更新过滤器选择以适应闪亮的 DT 数据表中已应用的过滤器

如何在闪亮的应用程序中观察 JavaScript 按钮

闪亮,两个动作按钮,它只响应第二个按钮而不响应第一个按钮

闪亮应用程序中的 RMarkdown

是否可以通过 vba 按钮启动闪亮的应用程序?