R shiny - идентификатор последней нажатой кнопки

У меня есть несколько кнопок действий, на которых я хочу показать разные входы выбора, и я хочу знать идентификатор последней нажатой кнопки, как я могу это сделать? Когда я использую

which(lapply(c(1:10), function(i) { input[[paste0("ActionButton", i)]]}) == TRUE)

Он показывает мне все кнопки, которые были нажаты, однако я хочу знать, какая из них была последней, чтобы снова включить щелчок по предыдущим кнопкам. Как я могу это сделать? Я новичок в блестящем и не уверен, что понимаю все проблемы с реактивностью / изоляцией, поэтому я был бы признателен за любые подсказки.


person user3463225    schedule 21.10.2016    source источник


Ответы (3)


Вы можете сделать это, добавив JS

что-то вроде

$(document).on('click', '.needed', function () {
                              Shiny.onInputChange('last_btn',this.id);
                             });

Пример (добавьте класс needed в btn, если вы хотите контролировать не все btn)

 ui <- shinyUI(fluidPage(

  titlePanel("Track last clicked Action button"),
  tags$head(tags$script(HTML("$(document).on('click', '.needed', function () {
                                Shiny.onInputChange('last_btn',this.id);
                             });"))),

  sidebarLayout(
    sidebarPanel(
      actionButton("first", "First",class="needed"),
      actionButton("second", "Second",class="needed"),
      actionButton("third", "Third",class="needed"),
      actionButton("save", "save"),
      selectInput("which_","which_",c("first","second","third"))
    ),

    mainPanel(

      textOutput("lastButtonCliked")
    )
  )
))


server <- shinyServer(function(input, output,session) {
  observeEvent(input$save,{
    updateSelectInput(session,"which_",selected = input$last_btn)
  })
  output$lastButtonCliked=renderText({input$last_btn})

})
# Run the application 
shinyApp(ui = ui, server = server)
person Batanichek    schedule 21.10.2016
comment
Большое спасибо. Не могли бы вы также объяснить, как сохранить текущие выбранные значения в кнопке selectInput? Предположим, у меня есть selectInput и actionButton «Сохранить». Для каждого щелчка «Сохранить» я хочу сохранить текущее выбранное значение в selectInput как updateSelectInput, не могли бы вы это добавить? Если хотите, могу добавить новый вопрос. - person user3463225; 21.10.2016
comment
Не совсем, я имел в виду, что если selectInput у меня есть choices = c (1: 5), selected = 1, и если я изменю в приложении selected value на 4 и нажму `` Сохранить '', кнопка selectInput обновит его выбранное значение до 4 (последний выбранное значение перед кнопкой «Сохранить») - person user3463225; 21.10.2016
comment
я действительно не могу понять, что вы хотите ... может быть лучше я задам новый вопрос - person Batanichek; 21.10.2016
comment
пожалуйста, обратитесь к вопросу stackoverflow .com / questions / 40171222 /, надеюсь, вам будет понятнее. - person user3463225; 21.10.2016

Этот код отслеживает, какая кнопка была нажата последним:

   library(shiny)


    ui <- shinyUI(fluidPage(


       titlePanel("Track last clicked Action button"),


       sidebarLayout(
          sidebarPanel(
            actionButton("first", "First"),
            actionButton("second", "Second"),
            actionButton("third", "Third")
          ),

          # Show a plot of the generated distribution
          mainPanel(
             textOutput("lastButtonCliked")
          )
       )
    ))


    server <- shinyServer(function(input, output) {

            rv <- reactiveValues(lastBtn = character())
            observeEvent(input$first, {
                    if (input$first > 0 ) {
                            rv$lastBtn = "first"
                    }
            })
            observeEvent(input$second, {
                    if (input$second > 0 ) {
                            rv$lastBtn = "second"
                    }
            })
            observeEvent(input$third, {
                    if (input$third > 0 ) {
                            rv$lastBtn = "third"
                    }
            })
            output$lastButtonCliked <- renderText({
                    paste("Last button clicked: ", rv$lastBtn)
            })
    })
    # Run the application 
    shinyApp(ui = ui, server = server)

Версия с лаппой с множеством кнопок. Благодарим @Victorp и этот ответ .

Это код:

    library("shiny")
    ui <- fluidPage(
            fluidRow(
                    column(
                            width = 6,
                            lapply(
                                    X = 1:5,
                                    FUN = function(i) {
                                            actionButton(inputId = paste0("button", i), label = paste("Button ", i))
                                    }
                            )
                    ),
                    column(
                            width = 6,
                            textOutput("lastButtonCliked")
                    )
            )
    )
    server <- function(input, output){

            rv <- reactiveValues(lastBtn = character())

            lapply(
                    X = 1:6,
                    FUN = function(i){
                            observeEvent(input[[paste0("button", i)]], {
                                    if (input[[paste0("button", i)]] > 0) {
                                            rv$lastBtn = paste0("button", i)    
                                    }
                            })
                    }
            )

            output$lastButtonCliked <- renderText({
                    paste("Last button clicked: ", rv$lastBtn)
            })
    }
    shinyApp(ui = ui, server = server)
person Valter Beaković    schedule 21.10.2016
comment
что, если у меня есть 100 кнопок действий, как написать так много событий? Предположим, что ваши кнопки начинаются с 'button' + X, где X от 1 до 100 - person user3463225; 21.10.2016

Существует третье решение, использующее тот факт, что каждая кнопка сохраняет количество нажатий. Если бы вы могли отслеживать это количество раз, то любое изменение этого числа укажет, какая кнопка была нажата.

Вот краткая реализация. На странице есть три кнопки (с произвольными названиями):

page <- shinyUI(basicPage(
    actionButton("firstbtn",label="Btn1"),
    actionButton("secondbtn",label="Btn2"),
    actionButton("thirdbtn",label="Btn3"),
    textOutput("result")
))

shinyServer <- function(input, output, session) {
    # the number of clicks on each button is zero at first
    oldBtnClicks <- rep(0,3)

    observeEvent({ obs <<- list(input$firstbtn, input$secondbtn, input$thirdbtn) }, ({
        # store all button state in a list
        BtnState <- obs

        # extract in a vector the number of clicks from each
        newBtnClicks <- rep(0,3)
        for (i in 1:3) 
            newBtnClicks[i] <- if (is.null(BtnState[[i]])) 0 else BtnState[[i]][1]

        # look for the change in the number of clicks
        buttonClicked <- match(1, newBtnClicks - oldBtnClicks)

        # show the button number that was clicked
        output$result <- renderText(expr = buttonClicked)
        
        # update hte number of clicks in the shinyServer environment
        oldBtnClicks <<- newBtnClicks

    }))
}

shinyApp(ui = page, server = shinyServer)

Функция сервера сначала устанавливает 0 для каждого нажатия кнопки (они еще не были нажаты). Затем устанавливается и наблюдатель, который ищет любую кнопку. Наблюдаемый список может быть произвольной длины.

Когда происходит событие, состояния кнопок извлекаются в виде списка (такого же, как и наблюдаемый список). Из этого списка извлекаются первые элементы каждого подсписка (это количество нажатий на эту конкретную кнопку); если некоторые кнопки могут быть скрыты (как это было в моем собственном приложении), список щелчков равен нулю, и поэтому количество щелчков устанавливается на 0 вручную.

Наконец, если взять разницу между прежним состоянием и новым состоянием, единственное место, которое не равно нулю (найденное с помощью match), - это позиция нажатой кнопки. После этого не забудьте обновить список состояний кнопок. И вуаля!

Если ваши кнопки имеют обычное имя (например, BtnX, где X идет от 1 до n), то может быть способ построить наблюдаемый список программно, а не путем ручного перечисления кнопок?

person Denis Cousineau    schedule 16.06.2021