0

quite a tricky situation here. I am trying to generate a UI to manage projects in an App. What I do is that each user has his list of projects stored somewhere, and from this list of project I generate, for each project, a div containing four buttons (later buttonTitle, continueProj, deleteProj and shareProj). Each of these buttons, when clicked, is supposed to trigger a function on the corresponding project.

To handle this, each time I get to the panel corresponding to this UI, I empty and generate an UI by project with insertUI, and fill a list for each action.

for (i in 1:(length(list_ui))){
  removeUI(
     selector = paste0('#',i)
   )
}
tit_obsList <<- list()
con_obsList <<- list()
del_obsList <<- list()
sha_obsList <<- list()
list_ui <<- list()

if(length(USER$list_of_projects !=0)){
for (i in 1:length(USER$list_of_projects)){
  insertUI(
    selector = '#placeholder',
    ui = tags$div(
      #class = "ProjectPanel",
      style = "background: #ffffff;
                     display: block; 
                     margin-left: auto; 
                     margin-right: auto;
                     width:1250px;
                     height:175px;
                     background-color: #ffffff;
                     color: #4a86e8;
                     border: #434343;",
      fluidRow(column(width = 11,
                      actionButton(inputId = paste0("buttonTitle_",USER$list_of_projects[i]),label = USER$list_of_projects[i],style = "background : #4a86e8;background-color: transparent;border-color : transparent; color: #4a86e8; font-size : 30px;")),
                      #tags$h3(paste(USER$list_of_projects[i]))), 
               column(width = 1,
                      tags$button(id = paste0("continueProj_",USER$list_of_projects[i]),class = "btn action-button",img(src = "icons/continue.gif",height = "40px"),style = "background-color: transparent;"))),
      fluidRow(column(width = 1,offset = 11,
                      tags$button(id = paste0("deleteProj_",USER$list_of_projects[i]),class = "btn action-button",img(src = "icons/delete_blue.png",height = "40px"),style = "background-color: transparent;"))),
      fluidRow(column(width = 1,offset = 11,
                      tags$button(id = paste0("shareProj_",USER$list_of_projects[i]),class = "btn action-button",img(src = "icons/share.gif",height = "40px"),style = "background-color: transparent;"))),
      id = i))
   #addPopover(session,paste0("deleteProj_",USER$list_of_projects[i]),"Hello")
  list_ui <<- c(list_ui,i)
  if (is.null(tit_obsList[[paste0("buttonTitle_",USER$list_of_projects[i])]])){
    # make sure to use <<- to update global variable obsList
    tit_obsList[[paste0("buttonTitle_",USER$list_of_projects[i])]] <<- observeEvent(input[[paste0("buttonTitle_",USER$list_of_projects[i])]], {
      continue_project(USER$list_of_projects[i])
    })
  }
  if (is.null(con_obsList[[paste0("continueProj_",USER$list_of_projects[i])]])){
    # make sure to use <<- to update global variable obsList
    con_obsList[[paste0("continueProj_",USER$list_of_projects[i])]] <<- observeEvent(input[[paste0("continueProj_",USER$list_of_projects[i])]], {
      continue_project(USER$list_of_projects[i])
    })
  }
  if (is.null(del_obsList[[paste0("deleteProj_",USER$list_of_projects[i])]])){
    # make sure to use <<- to update global variable obsList
    del_obsList[[paste0("deleteProj_",USER$list_of_projects[i])]] <<- observeEvent(input[[paste0("deleteProj_",USER$list_of_projects[i])]], {
    delete_project(USER$ID,USER$list_of_projects[i])
    removeUI(
      selector = paste0('#', i)
    )
    })
  }
  if (is.null(sha_obsList[[paste0("shareProj_",USER$list_of_projects[i])]])){
    # make sure to use <<- to update global variable obsList
    sha_obsList[[paste0("shareProj_",USER$list_of_projects[i])]] <- observeEvent(input[[paste0("shareProj_",USER$list_of_projects[i])]], {
      showModal(modalDialog(
        title = "You have decided to share your project",
        textInput("receiver_name","Please state the Login of the user you want to share your project with :"),
        hidden(p(id="enter_receiver","Please enter a user to share this project with ",style="font-size:10px;color:red;")),
        hidden(p(id="receiver_does_not_exist","This user does not exist",style="font-size:10px;color:red;")),
        hidden(p(id="receiver_has_access","This user already has access to this project",style="font-size:10px;color:red;")),
        footer = tagList(
          modalButton("Cancel"),
          actionButton("ok_shareProj", "OK")
          
        ),
        easyClose = TRUE
        )
      )
      if(input$receiver_name == ""){
        shinyjs::hide("receiver_does_not_exist")
        shinyjs::show("enter_receiver")
        shinyjs::hide("receiver_has_access")
      }
      else if(USER_in_database(input$receiver_name)==FALSE){
        shinyjs::show("receiver_does_not_exist")
        shinyjs::hide("enter_receiver")
        shinyjs::hide("receiver_has_access")
      }
      else if(has_access(input$receiver_name,USER$list_of_projects[i])){
        shinyjs::hide("receiver_does_not_exist")
        shinyjs::hide("enter_receiver")
        shinyjs::show("receiver_has_access")
      }
      else{
        invite_to_project(USER$ID,input$receiver_name,USER$list_of_projects[i])
        removeModal()
      }
    })
  
  }
}
  output$listproj <- renderText({unlist(USER$list_of_projects)})
  output$lenproj <- renderText({length(USER$list_of_projects)})
  output$uis <- renderText({unlist(tit_obsList)})
}

What is extraneous now is that, if I have no project, I can create them and all is working well : every button is functional. But if I reload the app, all UIs are present, but only the last button is working : if I have 3 projects P1, P2 and P3, only P3 buttons work, or more precisely, if I click to delete P2, nothing happens, but now if I click to continue P3, both events are triggered and P2 is deleted while P3 is continued. Another strange issue is that if I am in this same P1, P2, P3 situation and I delete P3, then P2 and only P2, the latter one, is functional again, while it was not before P3 was deleted. That means only the last one works.

I repeat that this only happens when I reload the app. If the app is not reloaded, all projects are functional, which is surprising because the list from which they are generated is the same and the place from which I call the code above is the same.

I hope someone can help me tackle this issue, thank you

  • Update : the problem might come from the lists of observers, as when I try to delete a project, it is effectively deleted when I delete the last one. Still no idea why it behaves this way when I reload the app and not before – Gaspar Roy May 24 '22 at 14:14
  • Perhaps you need to use `local()` in your `for` loop in `shiny`. Please look into it. – YBS May 24 '22 at 14:58
  • Sorry Gaspar, but the information you give us is too much on the one hand and too little on the other. The code sample is [neither minimum and nor reproducible (see this link)](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). I hope you find someone who can spot the problem just by looking at the code, but without being able to run it, my guess is, you need a lot of luck. In most cases, we need a piece of code that is small (with as little "noise" as possible), that replicates the issue, and that runs. – Jan May 25 '22 at 10:42
  • Sounds like a problem of the timing of execution of events that can perhaps be solved with isolating reactive values. A reproducible example would be needed to help you further. – guasi May 25 '22 at 21:19

0 Answers0