Блестящая проверка не показывает сообщение об ошибке

В моем приложении R Shiny есть два textAreaInput(), один для значений x, а другой для значений y. При нажатии кнопки подгоняется простая модель линейной регрессии, и результаты печатаются на основной панели. Это прекрасно работает.

Я пытаюсь проверить textAreaInput(), чтобы показать сообщение об ошибке

--- когда длина(x) != длина(y)

--- когда поля x или y пусты

--- когда поля x или y содержат недостаточно значений (менее двух пар данных)

--- когда поля x или y содержат NA или недопустимые символы

Вот минимальный репрекс-код. Я вижу, что проверки Shiny для вышеуказанных требований не отображаются должным образом на mainPanel, когда условия соблюдены. ИЗМЕНЕННЫЙ КОД НИЖЕ: Сделал код репрекса минимальным и удалил все reactive(), как советовали.

library(shiny)
library(shinythemes)
library(shinyjs)
library(shinyvalidate)

ui <- fluidPage(theme = bs_theme(version = 4, bootswatch = "minty"),
           
  navbarPage(title = div(span("Simple Linear Regression", style = "color:#000000; font-weight:bold; font-size:18pt")),

                tabPanel(title = "",
                  sidebarLayout(
                    sidebarPanel(
                      shinyjs::useShinyjs(),
                      id = "sideBar", 

                      textAreaInput("x", label = strong("x (Independent Variable)"), value = "87, 92, 100, 103, 107, 110, 112, 127", placeholder = "Enter values separated by a comma with decimals as points", rows = 3),
                      textAreaInput("y", label = strong("y (Dependent Variable)"), value = "39, 47, 60, 50, 60, 65, 115, 118", placeholder = "Enter values separated by a comma with decimals as points", rows = 3),

                      actionButton(inputId = "goRegression", label = "Calculate",
                                   style = "color: #fff; background-color: #337ab7; border-color: #2e6da4"),
                      actionButton("resetAllRC", label = "Reset Values",
                                   style = "color: #fff; background-color: #337ab7; border-color: #2e6da4"), #, onclick = "history.go(0)"
                    ),
                    
                    mainPanel(
                      div(id = "RegCorMP",
                            textOutput("xArray"),
                            
                            textOutput("yArray"),
                          
                            textOutput("arrayLengths"),

                            verbatimTextOutput("linearRegression"),
                      ) # RegCorMP
                  ) # mainPanel
               ) # sidebarLayout
          )
      )
  )
  
server <- function(input, output) {
    
    # Data validation
    iv <- InputValidator$new()

    iv$add_rule("x", sv_required())
    iv$add_rule("y", sv_required())

    iv$enable()
    
    # String List to Numeric List
    createNumLst <- function(text) {
      text <- gsub("","", text)
      split <- strsplit(text, ",", fixed = FALSE)[[1]]
      as.numeric(split)
    }

    observeEvent(input$goRegression, {
      
      datx <- createNumLst(input$x)
      daty <- createNumLst(input$y)

      if (length(datx)<2){
        output$xArray <- renderPrint({
          "Not enough x values"
        })
      }
      
      else if (length(daty)<2){
        output$yArray <- renderPrint({
          "Not enough y values"
        })
      }
      
      if (length(datx) != length(daty)) {
        print(length(datx))
        print(length(daty))
        
        output$arrayLengths <- renderPrint({
          "Length of x and length of y must be the same"
        })
      }
     
      else if (length(datx) == length(daty)) {
          output$linearRegression <- renderPrint({ 
            summary(lm(daty ~ datx))
          })
      }
    })

    observeEvent(input$goRegression, {
      show(id = "RegCorMP")
    })
    
    observeEvent(input$resetAllRC, {
      hide(id = "RegCorMP")
      shinyjs::reset("RegCorMP")
    })
}
  
shinyApp(ui = ui, server = server)```

Вложенность reactive — это рецепт катастрофы. Это скорее всего ваша проблема. Ваш observeEvent определяет несколько reactive внутри себя. Обычные правила области видимости R означают, что эти вложенные функции недоступны для других элементов вашего приложения.

Limey 17.01.2023 07:22

@Limey Любые советы о том, как выйти из катастрофы? Вы имеете в виду, что я должен использовать один отдельный observeEvent для каждого reactive утверждения?

Ash 17.01.2023 18:44

Нет. Я имею в виду, я думаю, что вы можете полностью отказаться от observeEvent. ВСЕ ваши reactiveobserveEvent, если необходимо) должны быть определены непосредственно в теле вашей серверной функции. Я не буду пытаться это сделать, потому что ваш код далеко не минимален: ни один из CSS не имеет прямого отношения к вашей проблеме. MathJax тоже нет. Ни radioButtons. И так далее. «Минимальная» часть MRE так же важна, как и «воспроизводимая». Дисциплина создания минимального воспроизводимого примера часто позволяет мне решить проблему до публикации вопроса.

Limey 17.01.2023 18:55

@Limey Спасибо за ваш совет, я удалил все reactive и сократил код до минимума. Сообщения проверки печатаются на mainPanel, хотя они также выводят результаты вместе с сообщениями, когда условия действительно выполняются. Любые советы о том, как распечатать тот или иной, т. е. предупреждение или правильные результаты. Сейчас он печатает оба.

Ash 17.01.2023 19:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что это близко к тому, что вы хотите. Обратите внимание, что каждый reactive определяется в теле серверной функции, а не в теле другого reactive. Это очень важно. А также полностью устраняет необходимость в вашем observeEvent.

Я удалил больше материалов (divs, themes и т. д.), которые не имеют отношения к вашему вопросу. Я тоже не уверен, что shinyjs нужен. Кроме того, я не уверен, что вы пытаетесь сделать с помощью кнопки сброса (похоже, она ничего не делает в данный момент), поэтому я оставил ее.

Я добавил проверку, чтобы убедиться, что ни в одном из входных данных нет NA, но предоставил вам реализовать проверку на равенство длины.

Кроме того, нет необходимости разделять ваши входные данные запятыми: достаточно пробелов... ;=)

library(shiny)
library(shinyjs)
library(shinyvalidate)

ui <- fluidPage(
        useShinyjs(),
        navbarPage(
          title = "Simple Linear Regression",
          tabPanel(
            title = "",
            sidebarLayout(
            sidebarPanel(
              id = "sideBar", 
              textAreaInput(
                "x", 
                label = strong("x (Independent Variable)"), 
                value = "87, 92, 100, 103, 107, 110, 112, 127", 
                placeholder = "Enter values separated by a comma with decimals as points", 
                rows = 3
              ),
              textAreaInput(
                "y", 
                label = strong("y (Dependent Variable)"), 
                value = "39, 47, 60, 50, 60, 65, 115, 118", 
                placeholder = "Enter values separated by a comma with decimals as points", 
                rows = 3
              ),
              actionButton(
                inputId = "goRegression", 
                label = "Calculate",
              ),
              actionButton(
                "resetAllRC", 
                label = "Reset Values",
              )
            ),
            mainPanel(
              div(
                textOutput("xArray"),
                textOutput("yArray"),
                textOutput("arrayLengths"),
                verbatimTextOutput("linearRegression"),
              ) # RegCorMP
            ) # mainPanel
          ) # sidebarLayout
        )
      )
    )

server <- function(input, output) {
  # Data validation
  iv <- InputValidator$new()
  iv$add_rule("x", sv_required())
  iv$add_rule("x", ~ if (any(is.na(as.numeric(strsplit(., ",", fixed = FALSE)[[1]])))) "NAs are not allowed")
  iv$add_rule("y", sv_required())
  iv$add_rule("y", ~ if (any(is.na(as.numeric(strsplit(., ",", fixed = FALSE)[[1]])))) "NAs are not allowed")
  iv$enable()
  # See https://rstudio.github.io/shinyvalidate/articles/advanced.html for clues on
  # how to implement length(x) == length(y) validation

  createNumLst <- function(text) {
    text <- gsub("","", text)
    split <- strsplit(text, ",", fixed = FALSE)[[1]]
    d <- as.numeric(split)
    if (length(d) < 2) "Not enough values"
    d
  }
  
  xData <- reactive({
    createNumLst(input$x)
  })
  
  yData <- reactive({
    createNumLst(input$y)
  })
  
  output$xArray <- renderPrint({ xData() })

    output$yArray <- renderPrint({ yData() })
  
  output$arrayLengths <- renderPrint({
    if (length(xData()) != length(yData())) "Length of x and length of y must be the same"
  })
  
  # Use isolate to ensure that results are updated only when action button is clicked, not 
  # every time the input data changes
  output$linearRegression <- renderPrint({
    input$goRegression
    isolate({
      summary(lm(yData() ~ xData()))
    })
  })
  
  observeEvent(input$goRegression, {
    show(id = "RegCorMP")
  })
  
  # Not sure what you are trying to do here
  observeEvent(input$resetAllRC, {
    hide(id = "RegCorMP")
    shinyjs::reset("RegCorMP")
  })
}

shinyApp(ui = ui, server = server)

Большое спасибо за ответы. divs, themes, shinyjs и т. д. полезны для более зрелого приложения Shiny, над которым я работаю ссылка. Этот конкретный пост был небольшой его частью, где я работал над простой линейной регрессией и хотел проверить поля x и ytextAreaInput. Кнопка «Сброс» предназначена для очистки всего (выходных данных, предупреждений, графиков и т. д.), отображаемого в данный момент на основной панели.

Ash 19.01.2023 03:07

«div, темы, блестящие и т. д. — все это полезно для более зрелого приложения Shiny, над которым я работаю по ссылке». Это все вполне разумно. Но они не имеют отношения к заданному вами вопросу.

Limey 19.01.2023 09:39

Другие вопросы по теме

Проверка ввода для строки в C
Вложенные ограничения Symfony не работают должным образом
В Sanity, как использовать проверку только в том случае, если для логического значения установлено значение true?
Как проверить на основе конкретного члена Enum в модели Fastapi Pydantic
Как проверить, начинается ли номер карты с префикса, принадлежащего набору предопределенных префиксов, используя C#?
Возможна ли проверка одного отправителя в Sendgrid без входа в систему?
В раскрывающемся списке применяется больше, чем отредактированная строка в appscript
Приложение .NET 6 Blazor Server — пользовательская аннотация проверки данных не работает должным образом
Собирайте только допустимые входные данные из пользовательской формы EXCEL VBA с несколькими вкладками и создавайте отчет для печати с отдельными разделами для каждой вкладки UF
JOI проверяет, есть ли в массиве только один соответствующий элемент. Не более одного