Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reset value of actionButton? #167

Closed
stratosfmos opened this issue Jun 7, 2013 · 72 comments
Closed

reset value of actionButton? #167

stratosfmos opened this issue Jun 7, 2013 · 72 comments

Comments

@stratosfmos
Copy link

stratosfmos commented Jun 7, 2013

can an actionbutton be reseted to 0 inside server.R?
let's say i have actionButton("b1","button1"). what could be the code for reseting the action button to 0?

@jcheng5
Copy link
Member

jcheng5 commented Jun 7, 2013

No, not at this time. Can you talk a little about why you want this? Thanks...

@stratosfmos
Copy link
Author

i was trying to bypass the issue with the radiobuttons(and the updateradiobuttons).so here is the logic. We have 2 buttons lets say b1 and b2. when a button is pushed then it is increased by 1 in server.R we render some text for this action.after it, the button must reseted to 0 so that if the state of a button is 1 it must trigger some text rendering and etc. but i think you gave me the answer. but it would be a nice addition for some ui control enhancement.what's your opinion?

@jcheng5
Copy link
Member

jcheng5 commented Jun 12, 2013

Don't think of the value of the input$actionButtonId as being meaningful, except for the special case of 0, which means "the button hasn't been pressed yet". In all other cases, you should just rely on the fact that input$actionButtonId changes and invalidates your reactive expression or observer. If you find yourself checking the actual value of input$actionButtonId (other than testing for 0) then it's a good sign you probably need to look again at using isolate:

# Take an action when button is clicked
observe({
  if (input$actionButtonId == 0)
    return()
  isolate({
    # Your logic here
  })
})

# Render text when button is clicked
output$text <- renderText({
  if (input$actionButtonId == 0)
    return("")
  isolate({
    # Your logic here
  })
})

@jcheng5 jcheng5 closed this as completed Jun 12, 2013
@xiaodaigh
Copy link
Contributor

Actually I think the reset is useful. I have an app that contains multiple projects. E.g. each project could be a different data set I am analysing, so when I switch projects I would want to reset all buttons as if they have never been pressed.

@sgrevers
Copy link

sgrevers commented Jun 3, 2014

I have the exact same problem where resetting the actionbuttons would help alot. An user is able to switch locations / working directories where he can analyse & create plots for different data sets. For all these different data sets the same plot buttons are being used. As soon as you would change the working directory now all scripts get called because buttons have been pressed already.

@sarvagna
Copy link

I'm facing this issue too. I have two buttons add and clear to build a query. when i select something and say add, that term should be added to query and if click on clear button, it should clear the query. i'm checking for add_button>0 now but that won't really solve my purpose because when i select something else after clicking add button it'll automatically be added to the query. i tried resetting the actionbutton value but really could not.

@sgrevers
Copy link

i did an odd workaround instead, using a var which i reset to 0 as soon as the button is pressed. I'm using input$h5fileName so the user can load another file.

observe ({
    input$h5fileName
    counter_createTime_Plot <<- 0
})

when call the function i want to run i increment this ensuring its run every time i actually press the actionButton.

observe({
    # increment the counter so i know it has been pressed
    if (counter_createTime_Plot == 0)
      counter_createTime_Plot <<- counter_createTime_Plot + 1

    #returning when the ui.R is opened the first time
    if (input$createTime_Plot == 0)
      return()

    # run the function because the button is clicked once after loading a new file
    else if (counter_createTime_Plot == 1) {
})

I use the counter value 1 to do a check if the file is correct, using a next if statement with if (counter_createTime_Plot > 1) to use the same actionButton for doing something else. It's not a pretty solution but for now it works the way i want it to. Being able to reset would still be much better.

@jcheng5
Copy link
Member

jcheng5 commented Jun 12, 2014

I still don't think you need this. If your add logic is surrounded by isolate you shouldn't have this problem. If I'm wrong, let me know.

@sgrevers
Copy link

in sarvagna's case most likely yes, since i suspect his input field is in the same observer as both actionButtons (maybe share the code?). In my case however i have a button which has to check the data input when it is clicked the first time, when clicking it for the second time it should not check the datainput but create a plot instead. A third click would do nothing since the data is validated and the plot has been made.

The user is also able to switch files however and as soon as he/she does the plot button became useless. In this situation it would be perfect if i could just reset the actionbutton instead when a a different file is loaded. Now i have to keep track how many times it is clicked with an external counter variable.

@sarvagna
Copy link

Here is my code, i tried to use the logic you mentioned. this works well first time i click either add or clear button. but after that the buttons are useless.

observe({
 if (input$add_button == 0)
   return()
   isolate({
  selected_term_ids<-c(input$thti,input$select_child_terms)
  if((!is.null(selected_term_ids)) & length(selected_term_ids)>0){
    onto <- input$search_option
  selected_terms <-    get_onto_terms_by_ids(paste0(selected_term_ids,collapse=","))
 } 
 if(!is.null(DisplayString$names)){
   DisplayString$names<-unique(append(DisplayString$names,selected_terms$term))
   QueryString$names<-unique(append(QueryString$names,selected_term_ids))
 }
 else{
   DisplayString$names<-selected_terms$term
   QueryString$names<-selected_term_ids
 }
 output$dynamic_value <- renderText({
   paste0(DisplayString$names, collapse=",")
 })
  })
if(input$clear_button == 0)
  return()
  isolate({
 DisplayString$names<- NULL
 QueryString$names <- NULL
 output$dynamic_value <- renderText({DisplayString$names})
})
 })

@jcheng5
Copy link
Member

jcheng5 commented Jun 19, 2014

Try using two observers, one for each button. Also, what are DisplayString and QueryString? Just normal lists or reactiveValues objects?

@sarvagna
Copy link

they are reactiveValues objects. I'll be using the displaystring in verbatimtextoutput and querystring in db query function further down the code

@jcheng5
Copy link
Member

jcheng5 commented Jun 19, 2014

In that case output$dynamic_value only needs to be assigned once, outside of any observer.

@sarvagna
Copy link

Well i did something like this and it seems to be working for now.

#Build query
  DisplayString <- reactiveValues()
  QueryString <- reactiveValues()

  observe({
    if (input$add_button > 0){
      isolate({
        selected_term_ids<-c(input$thti,input$select_child_terms)
        if((!is.null(selected_term_ids)) & length(selected_term_ids)>0){
          onto <- input$search_option
        selected_terms <- get_onto_terms_by_ids(paste0(selected_term_ids,collapse=","))
        } 
        if(!is.null(DisplayString$names)){
          DisplayString$names<-unique(append(DisplayString$names,selected_terms$term))
          QueryString$names<-unique(append(QueryString$names,selected_term_ids))
        }
        else{
          DisplayString$names<-selected_terms$term
          QueryString$names<-selected_term_ids
        }
      })
    }
#Clear selection
if(input$clear_button >= input$add_button){
  isolate({
    DisplayString$names<- NULL
    QueryString$names <- NULL
  })
}
  })

  #Show selected terms
  output$dynamic_value <- renderText({
    paste0(DisplayString$names, collapse=",")
  })

@sharko666
Copy link

I really wish one could reset an actionButton to 0.

@jcheng5
Copy link
Member

jcheng5 commented Oct 13, 2014

@sharko666 Let me know if you have a simple example of why you need that. I'm totally open to being convinced but haven't seen any scenarios so far that weren't better handled using the idioms we've already established.

@Marccohen
Copy link

Joe, Did you send this to me by mistake? I'm not sharko666.

On Mon, Oct 13, 2014 at 11:29 AM, Joe Cheng notifications@github.com
wrote:

@sharko666 https://github.com/sharko666 Let me know if you have a
simple example of why you need that. I'm totally open to being convinced
but haven't seen any scenarios so far that weren't better handled using the
idioms we've already established.


Reply to this email directly or view it on GitHub
#167 (comment).

Marc-david Cohen | Chief Science Officer | +1.415.205.6295 |
www.aktana.com

The power of many, the focus of one

@wch
Copy link
Collaborator

wch commented Oct 13, 2014

@Marccohen You probably got a copy of the message because you're watching the shiny repository on github.

@sharko666
Copy link

Hi Joe,
I'm working on a application which takes an URL into a text field and loads data sets from an URL. That works fine as long as the user copy and pastes the URL into the text field. If there is a mistake in the URL or it is typed in, shiny constantly tries to load data from an unfinished URL. That's why I thought I add a submit button to it. That improved things that now the URL also can be typed in as nothing happens as long as the button is pressed. The new problem arises when another URL after the first one is typed in. The counter is already higher than 0 so the button is marked as pressed. So this works only for the first time. This problem would have been easily solved if there would be a way to reset the counter in the logic part when the dataset is loaded or an appropriate error (if the URL is still wrong) is caught.

Now, I found a solution but it might not be the solution as shiny is supposed to work. I have a global variable set in the reactiveValues function called actionCounter. Every time the button is pressed the buttoncounter is increased and is higher than the actionCounter. Inside the logic the action counter is set to the buttoncounter. Now I only test whether the actionCounter is lower than the buttonCounter. See code below.

#server.R

vars = reactiveValues(actionCounter=0)

inside the observer for the textfield

url = input$URL_input
if(!is.null(input$submit_URL)){
if(input$submit_URL>vars$actionCounter&url!=""){
vars$actionCounter=input$submit_URL
# try load the data
}
}

So there is a relative easy solution but if there were the possibility to reset the button counter it would have been simpler and easier to understand.

Regards

Christoph


From: Marc Cohen [notifications@github.com]
Sent: Tuesday, October 14, 2014 7:37
To: rstudio/shiny
Cc: Christoph Knapp
Subject: Re: [shiny] reset value of actionButton? (#167)

Joe, Did you send this to me by mistake? I'm not sharko666.

On Mon, Oct 13, 2014 at 11:29 AM, Joe Cheng notifications@github.com
wrote:

@sharko666 https://github.com/sharko666 Let me know if you have a
simple example of why you need that. I'm totally open to being convinced
but haven't seen any scenarios so far that weren't better handled using the
idioms we've already established.


Reply to this email directly or view it on GitHub
#167 (comment).

Marc-david Cohen | Chief Science Officer | +1.415.205.6295 |
www.aktana.com

The power of many, the focus of one


Reply to this email directly or view it on GitHubhttps://github.com//issues/167#issuecomment-58935448.

@jcheng5
Copy link
Member

jcheng5 commented Oct 13, 2014

Thanks for the feedback. This is the idiomatic way to handle such a situation:

url <- reactive({
  if (input$submit_URL == 0) {
    return(NULL)
  }
  isolate(input$URL_input)
})

Then everywhere you want to access the URL, use url().

It is a longstanding grievance against Shiny that we don't have wrapper functions for this idiom.

@jcheng5
Copy link
Member

jcheng5 commented Oct 13, 2014

@sharko666 I just merged a very longstanding pull request into master. With this change you can now do this instead:

url <- reactive({
  eventFilter(input$submit_URL, input$URL_input)
})

This basically means "the value of url is nothing (NULL) at first, but every time input$submit_URL is clicked, set it to the then-current value of input$URL_input".

There is a complementary observeEvent function as well:

observeEvent(input$submit_URL, function() {
  # Do something involving input$URL_input
})

The "do something" part of the code will be executed when and only when the button is clicked.

@dakshvarma
Copy link

@jcheng5 I just used the new version of Shiny - 10.2.9 for the new observeEvent function. It works great on my desktop version of R studio, but I am trying to run this using a portable R and Chrome install from a flash drive. This worked fine with shiny 10.2.1 because I was able to find a zip that worked for shiny 10.2.1. I have tried going though github, but am not sure how I can find (or create) a 10.2.9 zip that will work for a portable (32 bit) install of R. If you could point be in the right direction that would be much appreciated. Thanks :)

@jcheng5
Copy link
Member

jcheng5 commented Oct 22, 2014

@dakshvarma Is there a reason that devtools::install_github` wouldn't work with your portable R?

@dakshvarma
Copy link

@jcheng5 Got it working finally! devtools::install_github installs it by creating a local folder. The trick is to zip up the local folder, install a package from the zip in the portable install (with the zip in the same folder as portable R). Thanks for your help!

@hrasof
Copy link

hrasof commented Nov 18, 2014

i have the following case:
2 actionsbuttons (Generate and Reset) that should be used under ONE renderPlot.
How to handle this situation? Appreciate your help

output$Result <- renderPlot({
  if(input$GEN_button == 0){
    # mylogic
  }
  else if(input$RES_button == 0){
    # mylogic
  }
  else {
    # mylogic
  }
})  

@jcheng5
Copy link
Member

jcheng5 commented Nov 18, 2014

What does Reset do, clear it? What should the initial state of the plot
be--should it be generated when the app first starts up, or should it be
blank?

On Tue, Nov 18, 2014 at 8:37 AM, Hratch notifications@github.com wrote:

i have the following case:
2 actionsbuttons (Generate and Reset) that should be used under ONE
renderPlot.
How to handle this situation? Appreciate your help

output$Result <- renderPlot({
if(input$GEN_button == 0){
# mylogic
}
else if if(input$RES_button == 0){
# mylogic
}
else {
# mylogic
}
})


Reply to this email directly or view it on GitHub
#167 (comment).

@hrasof
Copy link

hrasof commented Nov 18, 2014

Reset sets back the value of the matrix to be plotted to an initial value.
The initial state (Initial run) should show plot the matrix that is created within the logic.
If Generate Button is clicked then a new matrix will be generated and plotted.

That means the matrix can be calculated outside the renderPlot too right?

@jcheng5
Copy link
Member

jcheng5 commented Nov 18, 2014

In that case, it sounds like both Generate at Reset should affect not the
plot directly, but a matrix value.

initialMatrixValue <- ...
shinyServer(function(input, output, session) {
  values <- reactiveValues(matrix = initialMatrixValue)
  observe({
    if (input$GEN_button == 0)
      return()
    values$matrix <- ... # Generate the matrix here
  })
  observe({
    if (input$RES_button == 0)
      return()
    values$matrix <- initialMatrixValue
  })
  output$Result <- renderPlot({
    plot(values$matrix) # or whatever
  })
})

@hrasof
Copy link

hrasof commented Nov 19, 2014

Thank you for your fast feedback/solution, you're great.

@nhpackard
Copy link

I, too, find myself wanting to reset an action button. I don't find the following functionality in the thread so far, so I'll try it out for Joe...

It has to do with using a conditional panel that looks at an action button value for its condition (this is in ui.R, not server.R).

In a sidePanel I have something like:

sidePanel(
...
actionButton(doit,"Configure this variable")
...
)

then in a main panel I have something like

mainPanel(
   ...
   # for action button not pushed:
   conditionalPanel(condition="input.doit == 0 & input.tabs==...",
                                ...),
   ...
   # for action button pushed:
   conditionalPanel(condition="input.doit > 0 & input.tabs==...",
                                ...),

Now, at some point (maybe triggered by another action button, I would like to reset input.doit and re-display the first conditional panel, have the user re-specify inputs there, etc. Seems like it would be quite natural to have something like updateActionButton() over in server.R to get me back to my first conditional panel.

I would be very happy to hear the 'right and proper' way to do this, given that updateActionButton() does not exist.

@irJoostvanVeen
Copy link

To get a 0 / 1 actionbutton without resetting:

attr(input, "readonly") <- FALSE
input$ActionButtonMemory <- 0
observe({
  if(length(input$ActionButton)>0){
  if((input$ActionButton-input$ActionButtonMemory)>0){
    input$ActionButtonMemory<- input$ActionButton # Equalize
    # DO YOUR THING HERE
  }}
})

@mikebirdgeneau
Copy link

I stumbled upon this issue, while looking for a way to write a single handler that can respond to a large number of individual (dynamically changing) action buttons. Here's an example of what I was trying to do:

save_settings <- function()
  {
    xs <- seq(1,100,by=1)
    result<-lapply(xs,function(x){
      observeEvent(input[[paste0(x,"_save")]], {
            if(!(input[[paste0(x,"_save")]]==0)){
        # Save something for this value of x.
        #input[[paste0(x,"_save")]] <- 0 # Could be a nice place to be able to reset to 0.
            }
          }
        }
        message(paste0(x,"_save: ",input[[paste0(x,"_save")]]))
      })
      input[[paste0(x,"_save")]]
    })
    return(result)
  }
})

I could see the 'reset' to zero being useful in this case, but perhaps there's a better way of doing this.
Has anyone done something similar?

@jcheng5
Copy link
Member

jcheng5 commented Oct 30, 2015

@mikebirdgeneau That's absolutely not necessary in this case. This is all you need to do:

save_settings <- function() {
  xs <- seq(1,100,by=1)
  lapply(xs,function(x){
    observeEvent(input[[paste0(x,"_save")]], {
      # Save something for this value of x.
    })
  })
}

@mikebirdgeneau
Copy link

@jcheng5 thanks - I'll give that a go! Appreciate the quick response. Cheers.

@dcenergy-reeve
Copy link

I can see one argument for resetting an actionButton that I haven't seen mentioned here (apologies if it has been mentioned, and I missed it). I'd like to be able to copy the URL from the browser in which my shiny app is running, send it to somebody else, and have them be able to load the same page with all of the inputs automatically populated from the URL. I do not, however, want the actions executed by an actionButton to run automatically. (One example of this might be a page used to visualize data, with an actionButton that will trigger the writing of that data to a particular file. I want to be able to send a visualization of that data to somebody by sending them the URL to my page, but they may not want to write it to file upon page load).

By default shiny can save/load all of its input variables to/from the URL, which is great most of the time, but can cause issues when it loads actionButtons with values > 0. In those cases, as in the example above, it will think that the user has clicked the actionButton when in reality he/she has not yet done so.

This is a case in which the value of the actionButton does not matter, but the fact that it is not zero is important. Thanks for your help!

@jcheng5
Copy link
Member

jcheng5 commented Oct 30, 2015

By default shiny can save/load all of its input variables to/from the URL

That's not a built-in feature of Shiny; is there a specific package you're using to give you that functionality?

@dcenergy-reeve
Copy link

You're right - this is part of a separate package (that is not yet publicly available). Thank you for the quick response.

@chris-holcomb
Copy link

@nhpackard does shinyjs help you accomplish what you need? Here's a minimal example of toggle:

library(shiny);library(shinyjs)

shinyApp(
  ui = fluidPage(
    sidebarLayout(
      sidebarPanel(
        actionButton("showPanel","Show Panel!")
      ),
      mainPanel(
        useShinyjs(),
        absolutePanel(id = "panel", class = "panel panel-default",
                      style = "z-index:100; display: none;",

                      div(style="margin:10px;",
                          h3("Hello World")
                      )
        )
      )
    )
  ),
  server = function(input, output) {

    observeEvent(input$showPanel,{
      toggle("panel")
    }) 

  }
)

It's not using conditionalPanel but I think it's cleaner to keep the logic on the server-side. Upon a button press you could have it updateX for each of the inputs, and run the analysis, etc.

@abhijeetgosavi
Copy link

Hi Joe,

I stuck around the similar problem related to the resetting of action button. My problem is

On UI : I have 1 drag down which contains 2 values "Suntrust Bank" and "Huntington Bank". And below which i have 3 action buttons for 3 task : process data, download processed data and upload processed data.

When i select Suntrust first time, below three action buttons are not executed unless i pressed them. However, whenever i select Huntington, below 3 buttons executed automatically (buttons were not pressed) .

Could you please help me out how to resolve this ? Ideally i would like to have : when i change SunTrust to Huntington or and again Huntington to SunTrust, the below 3 buttons (process, download and upload) should not work unless and until i press them.

Thanks in advance !!

@jcheng5
Copy link
Member

jcheng5 commented Jan 26, 2016

Like this:

observeEvent(input$process, {
# processing code here
})
observeEvent(input$download, {
# download code here
})
observeEvent(input$upload, {
# upload code here
})

On Tue, Jan 26, 2016 at 10:18 AM abhijeetgosavi notifications@github.com
wrote:

Hi Joe,

I stuck around the similar problem related to the resetting of action
button. My problem is

On UI : I have 1 drag down which contains 2 values "Suntrust Bank" and
"Huntington Bank". And below which i have 3 action buttons for 3 task :
process data, download processed data and upload processed data.

When i select Suntrust first time, below three action buttons are not
executed unless i pressed them. However, whenever i select Huntington,
below 3 buttons executed automatically (buttons were not pressed) .

Could you please help me out how to resolve this ? Ideally i would like to
have : when i change SunTrust to Huntington or and again Huntington to
SunTrust, the below 3 buttons (process, download and upload) should not
work unless and until i press them.

Thanks in advance !!


Reply to this email directly or view it on GitHub
#167 (comment).

@abhijeetgosavi
Copy link

Yes, exactly. Let me paste my server.r code here
Server.r

library(data.table)
library(shiny)
library(stats)

shinyServer(function(input, output, session) {

  datasetInput <- reactive({
    switch(input$Select,
      "SunHE" = heloc.comp.rate, 
      "HunHE" = heloc.comp.rate1
    )
  })

  observeEvent(input$goButton, {
    output$MyData <- renderDataTable({
      datasetInput()
    })
  })

  observeEvent(input$Click, {
    output$fill <- renderUI({ 
      write.csv(datasetInput(), file.loc,row.names=FALSE)
    }) 
  })

  observeEvent(input$Submit, {
    output$fill <- renderUI({ 
      write.csv(datasetInput(), Up.file.loc,row.names=FALSE)
    })  
  })
})

ui.r

shinyUI(fluidPage(
titlePanel("Generate Competitor rate GI file"),

sidebarLayout(

sidebarPanel(

 selectInput("Select","Select Customer:", 
                    list(SunHE = "SunHE", HunHE  = "HunHE")
                    ) ,

 actionButton("goButton", "Generate GI File")  ,

 actionButton("Click", "Download GI File")  ,

 actionButton("Submit", "Upload GI File"),


uiOutput("fill") ,

uiOutput("Upload")
         )

    ,

mainPanel(
  h3(textOutput("caption")),
  dataTableOutput("MyData")
         )
         )

))

When i'm changing bank from Suntrust to Huntington from Drag n Down, below 3 actions buttons are executing automatically.

@jcheng5
Copy link
Member

jcheng5 commented Jan 26, 2016

Can we take the discussion over to shiny-discuss? Thanks.

@abhijeetgosavi
Copy link

I have created new discussion - Resetting action buttons. Kindly have a look and let me know if you have any inputs.

Thanks.

@subhashjaini
Copy link

was this ever resolved or did they just keep insisting that nobody needed it? I need it! :)

@resurrexi
Copy link

I was wondering if there was a resolution to this as well. I need the actionButton reset because I have a conditionalPanel that depends on whether the button is clicked, but it has to be reset whenever the user switches options in my dropdown menu.

@subhashjaini
Copy link

subhashjaini commented Mar 8, 2018 via email

@johnpauls
Copy link

johnpauls commented Mar 8, 2018

In general what you need is reactiveValue that is tied to the button. Every the the button is clicked it adds one to the value, and that value is used to trigger observers etc. Then, when the user does the stuff that resets things, just reset the reactiveValue to 0, the value tied to the button can stay as it is.

@resurrexi
Copy link

I ended up using shinyjs to create a hidden checkboxInput that would be toggled by several observers. Then, in my UI, I set up a conditionalPanel to check for the T/F value from the checkboxInput, and display the button if TRUE.

@RobertMyles
Copy link

@thomaszwagerman
Copy link

thomaszwagerman commented Aug 20, 2019

I am experiencing a similar problem when using multiple embedded observeEvents, where a reset of the actionButton value would be useful.

For example:

     observeEvent(input$button1, { 
     #a modal with button2 pops up, but should not trigger button2 until clicked
     actionButton("button2", "Button 2")

     observeEvent(input$button2, {
      #modal number 2 pops up
      #some action
      removeModal()
      })
 })

This structure works perfectly in the first instance. However, when triggering button1 for the second time, it skips straight to observeEvent button2, without input$button2 having been provided.

A bit more investigating with browser() showed that input$button2 retains its value despite closing the modal and triggering input$button1 again, UNLESS a modalButton is used to dismiss the modal instead of removeModal().

A hard reset of the button in this case would be useful in conjunction with removeModal(), to prevent the app user from having to click a "Dismiss"-style modalButton every time.

Previously I have used updateRadioButtons to reset inputs for a selection menu, but this doesn't work the same with actionButtons.

I haven't found a suitable solution above, but I very much hope to be corrected by someone!

Thanks a lot.

@sa-ccr
Copy link

sa-ccr commented Jun 6, 2020

that's an obviously useful feature - is there any piece of reasoning why this is not fixed???

@TjebsC
Copy link

TjebsC commented Jun 15, 2020

I am experiencing a similar problem when using multiple embedded observeEvents, where a reset of the actionButton value would be useful.

For example:

     observeEvent(input$button1, { 
     #a modal with button2 pops up, but should not trigger button2 until clicked
     actionButton("button2", "Button 2")

     observeEvent(input$button2, {
      #modal number 2 pops up
      #some action
      removeModal()
      })
 })

This structure works perfectly in the first instance. However, when triggering button1 for the second time, it skips straight to observeEvent button2, without input$button2 having been provided.

A bit more investigating with browser() showed that input$button2 retains its value despite closing the modal and triggering input$button1 again, UNLESS a modalButton is used to dismiss the modal instead of removeModal().

A hard reset of the button in this case would be useful in conjunction with removeModal(), to prevent the app user from having to click a "Dismiss"-style modalButton every time.

Previously I have used updateRadioButtons to reset inputs for a selection menu, but this doesn't work the same with actionButtons.

I haven't found a suitable solution above, but I very much hope to be corrected by someone!

Thanks a lot.

I'm having the same issue which is really annoying when having two modals back-to-back where the first one shows missing data for a selection. Could not find suitable workaround either

@TjebsC
Copy link

TjebsC commented Jun 15, 2020

I'm having the same issue which is really annoying when having two modals back-to-back where the first one shows missing data for a selection. Could not find suitable workaround either

Ok. For future reference to people having the same problem as me. The easy solution for me was to include shinyjs::onclick() instead of observeEvent. Then it works every time. A short snippet of my code:

`
observeEvent(input$change, {
showModal(modalDialog(title = "some_title",
renderTable({#my data}),
easyClose = FALSE,
footer = tagList(actionButton("ok", "Ok"), shinyjs::useShinyjs())))

shinyjs::onclick("ok", {
  removeModal()

  # My other modal is in a module. Should work outside as well
  callModule(pop_up, "dato", dato_tabell = reactive({pop_up_data()}))
})

}
)
`

Sorry for terrible formatting. Hope this helps somebody

@jcheng5
Copy link
Member

jcheng5 commented Jun 16, 2020

@TjebsC For future reference, you can work around this by giving observeEvent(input$button2, ...) an additional argument ignoreInit=TRUE. What this tells observeEvent is, "no matter what the current value of input$button2 is, don't execute this observer until the NEXT time input$button2 is updated". Not very intuitive, but I think it should work.

Oh, ha, this exact scenario is laid out in ?observeEvent (though I don't blame you for not coming across it):

For example, if you're setting up an observeEvent for a dynamically created button, then ignoreInit = TRUE will guarantee that the action (in handlerExpr) will only be triggered when the button is actually clicked, instead of also being triggered when it is created/initialized.

@MartinY96
Copy link

MartinY96 commented Jul 6, 2020

ok, I am a same problem.

    #SAVE
    observeEvent(input$Guardar,{
    req(input$Guardar)
        
       input$Guardar
       isolate({
        
                archivo <- paste0("D:/",
                                  input$Fundo, "-", input$Parcela, " ", 
                                  input$Lote, " ", input$Lado,".pdf")
                
                pdf(archivo, width = 18, height = 11 )
                
                Graph
                
                dev.off()
                
                shinyalert(title = "Descarga Correcta", type = "success")
                

        })

I have this code inside an observeEvent to save every time I make changes to a map, the problem is that as soon as a parameter change is saved, I mean when I click on the save button, and it doesn't stop working; I would like it to only save when I click.
I need help, please.

@philibe
Copy link

philibe commented Oct 20, 2021

A method written after I've read this issue and the last message of @jcheng5 about observeEvent(,{},ignoreInit=TRUE):

react <- reactiveValues(
  BtnSubmit=0,
  authorization=FALSE 
)

observeEvent(input$BtnSubmit,{
  # https://github.com/rstudio/shiny/issues/167 "reset value of actionButton?"
  react$BtnSubmit=1

  res<-FALSE
  res_before<-isolate(react$authorization)
  
  if (DescTools::Coalesce(react$BtnSubmit,0)>0) {
    react$BtnSubmit=0
    if (my_verification_else_where) {
      res<-TRUE
      react$authorization<-res
    } else {
      res<-FALSE
      react$authorization<-res
    }
  } else {
    res<-res_before
  }
  res
  
}, ignoreInit=TRUE) 



Table.react <- reactive ({
  validate(
    need(react$authorization, "Forbidden Access ! ")
  )
  data_frame_for_renderDataTable
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests