R Блестящая кнопка альтернативного действия

#r #shiny

Вопрос:

У меня есть простое приложение , в котором при каждом щелчке plus1 значение x увеличивается на 1, а при каждом щелчке plus10 значение x увеличивается на 10. Но я хочу plus10 , чтобы это было действительным только после plus1 нажатия. И после plus1 того, как нажата, plus10 может быть нажата только один раз, прежде чем снова станет недействительной, что потребует еще одного щелчка plus1 , чтобы сделать ее действительной. Поэтому в основном я хочу, чтобы пользователь нажимал эти две кнопки поочередно, причем plus1 сначала нужно нажать, когда приложение будет запущено. В идеале пользователю должно быть выдано предупреждение, если пользователь попытается нажать plus10 , не нажимая plus1 первым: «Пожалуйста, сначала нажмите плюс 1».

 library(shiny)

ui <- fluidPage(
  actionButton("plus1", "  1"),
  actionButton("plus10", "  10"),
  textOutput("value")
)

server <- function(input, output, session) {
  x = reactiveVal(0)
  
  observeEvent(input$plus1,{
    x(x() 1) # increment x by 1
  })
  
  observeEvent(input$plus10,{
    x(x() 10) # increment x by 1
  })
  
  output$value = renderText(x())
}

shinyApp(ui, server)
 

Ответ №1:

Это делает то, что вы хотите, но зачем вам это нужно?

 library(shiny)

ui <- fluidPage(
    actionButton("plus1", "  1"),
    actionButton("plus10", "  10"),
    textOutput("value"),
    textOutput("warning")
)

server <- function(input, output, session) {
    x = reactiveValues(x=0,click1=TRUE)
    
    observeEvent(input$plus1,{
        if (x$click1) {
            x$x <- x$x 1 # increment x by 1
            x$click1 <- !x$click1
        } else {
            output$warning <- renderText({"Please click plus10 first"})
        }
        
    })
    
    observeEvent(input$plus10,{
        if (!x$click1) {
            x$x <- x$x 10 # increment x by 10
            x$click1 <- !x$click1
        } else {
            output$warning <- renderText({"Please click plus1 first"})
        }
    })
    
    output$value = renderText(x$x)
}

shinyApp(ui, server)
 

Дайте мне знать, если потребуется объяснение

Комментарии:

1. Это всего лишь упрощенная версия того, что я пытаюсь сделать, но таким образом проще наметить проблему. У меня есть две кнопки в приложении, одна называется «одобрить», а другая — «Следующая страница». И я не хочу, чтобы пользователь переходил на следующую страницу, если он не утвердил документ.

2. Отличный ответ, я не знал, что вы можете использовать такие реактивные значения.

Ответ №2:

С помощью shinyjs :

 library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  actionButton("plus1", "  1"),
  disabled(actionButton("plus10", "  10")),
  textOutput("value")
)

server <- function(input, output, session) {
  x = reactiveVal(0)
  
  observeEvent(input$plus1,{
    x(x()  1 )
    disable('plus1')
    enable('plus10')
  })
  
  observeEvent(input$plus10, {
    x(x()   10)
    enable('plus1')
    disable('plus10')
  })
  
  output$value <- renderText({x()})
}

shinyApp(ui, server)
 

Комментарии:

1. обожаю эту посылку! В пакете есть и другие полезные функции, спасибо!

Ответ №3:

Вы можете просто добавить другое реактивное значение, чтобы отслеживать, может ли пользователь добавить 10

 library(shiny)

ui <- fluidPage(
  actionButton("plus1", "  1"),
  actionButton("plus10", "  10"),
  textOutput("value")
)

server <- function(input, output, session) {
  x <- reactiveVal(0)
  canPlus10 <- reactiveVal(FALSE)
  
  observeEvent(input$plus1,{
    x(x() 1) # increment x by 1
    canPlus10(TRUE)
  })
  
  observeEvent(input$plus10,{
    if (canPlus10()) {
      x(x() 10) # increment x by 10
    } else {
      showNotification("Please click  1 first")
    }
    canPlus10(FALSE)
  })
  
  output$value = renderText(x())
}

shinyApp(ui, server)
 

Комментарии:

1. Это прекрасный ответ, который можно легко масштабировать для более сложных приложений с этой проблемой. Ваш ответ, однако, пользователь может нажать на кнопку plus1 несколько раз, и я намерен, чтобы пользователь мог нажать на нее только один раз. Но, используя вашу логику, мне удается создать другое реактивное значение, называемое canPlus1 = reactiveVal(TRUE), и использовать некоторую логику в операторе if else, чтобы заставить его работать. Спасибо!