如何在Shiny中通过文本输入更新滑块范围?报错Result must have length 10, not 0
Fixing the "Result must have length 10, not 0" Error in Your Shiny App
Let's break down what's causing your error and fix it step by step:
Key Issues in Your Code
- Empty Dataset Filtering: When you select "All" in the site dropdown, your original
filter(SiteNameNew == input$SiteNameNew)tries to match against a value that doesn't exist in your data ("All"), resulting in an empty dataset. Callingmax(data$Year)on an empty dataset returnsNA, and the subsequentif/elsechecks fail because they expect a valid length-1 result. - Reactive Value Misuse: The
rangeobject returned by yourcontrolledSlidermodule is a list of reactive values. You need to call them with parentheses (range$min(),range$max()) to get their current values—using them directly without parentheses uses the reactive object itself, not its value. - Incorrect Condition Check: The
if (range != "All")check in your table output is invalid becauserangeis a reactive list, not a string. This check will always evaluate toTRUE, leading to unexpected filtering behavior. - Missing Module Definition: Your code references a
controlledSlidermodule but doesn't include its definition—this is critical for the input box/slider interaction to work properly.
Fixed Full Code
First, add the missing controlledSlider module definition, then fix the filtering logic:
library(shiny) library(ggplot2) library(readxl) library(DT) library(dplyr) # Define the controlledSlider module UI controlledSliderUI <- function(id) { ns <- NS(id) tagList( sliderInput(ns("slider"), "River Mile Range", min = 0, max = 100, value = c(0, 100)), numericInput(ns("min_input"), "Min River Mile", value = 0), numericInput(ns("max_input"), "Max River Mile", value = 100), actionButton(ns("update"), "Update Slider") ) } # Define the controlledSlider module server controlledSlider <- function(input, output, session, min_val, max_val, initial_value) { ns <- session$ns # Initialize slider with correct bounds updateSliderInput(session, "slider", min = min_val, max = max_val, value = initial_value) # Update slider when button is clicked, with validation observeEvent(input$update, { new_min <- input$min_input new_max <- input$max_input if(new_min >= min_val && new_max <= max_val && new_min <= new_max){ updateSliderInput(session, "slider", value = c(new_min, new_max)) } else { showNotification("Invalid values: Min must be ≤ Max, and both must fit within the slider range", type = "error") } }) # Return reactive min/max values return(list( min = reactive(input$slider[1]), max = reactive(input$slider[2]) )) } #Fake Data MSGRAIN <- data.frame("Year" = c(2018,2018,2018,2017,2016,2010,2010,2000,2000,2000), "SiteNameNew" = c('A','B','B','B','C','C','C','C','D','D'), "RiverMile" = 550:559) ui <- fluidPage( # Selection Bar fluidRow( #Select by River Mile (Manual Input) column(5, controlledSliderUI('RiverMile') ), #Select By Site column(5, selectInput("SiteNameNew", "Site Name:", c("All", unique(as.character(MSGRAIN$SiteNameNew)) ) ) ), column(6,h4(textOutput('test')) ), #Create a new row for the table DT::dataTableOutput("table") ) ) server <- function(input, output, session) { # Initialize the controlled slider with your data's bounds range <- callModule(controlledSlider, "RiverMile", min_val = min(MSGRAIN$RiverMile), max_val = max(MSGRAIN$RiverMile), initial_value = c(min(MSGRAIN$RiverMile), max(MSGRAIN$RiverMile)) ) # Current Year cyear <- as.numeric(format(Sys.Date(), "%Y")) # Output to show if selected area has been tested in the last 5 years output$test <- renderText({ data <- MSGRAIN %>% filter( # Filter by site only if "All" isn't selected if(input$SiteNameNew != "All") SiteNameNew == input$SiteNameNew else TRUE, RiverMile >= range$min(), RiverMile <= range$max() ) # Handle empty dataset case first if(nrow(data) == 0){ "No data found for the selected criteria." } else { latest_year <- max(data$Year) if (latest_year >= cyear - 5){ "This site has been tested in the last 5 years." } else { "This site has not been tested in the last 5 years." } } }) output$table <- DT::renderDataTable(DT::datatable({ MSGRAIN %>% filter( if(input$SiteNameNew != "All") SiteNameNew == input$SiteNameNew else TRUE, RiverMile >= range$min(), RiverMile <= range$max() ) }) ) } # Run the application shinyApp(ui = ui, server = server)
What Changed?
- Added the
controlledSlidermodule: This implements the input box/slider sync with validation to prevent invalid range values. - Fixed site filtering: Used a conditional
if()insidefilter()to skip site filtering when "All" is selected. - Handled empty datasets: Added a check for
nrow(data) == 0to avoid errors when no data matches the selected criteria. - Used reactive values correctly: Added parentheses to
range$min()andrange$max()to access their current values. - Removed invalid condition check: Replaced the broken
range != "All"check with consistent filtering logic.
This should resolve the "Result must have length 10, not 0" error and make your app behave as expected.
内容的提问来源于stack exchange,提问作者Alex Morrison
相关产品推荐
相关产品推荐

