动态呈现的UI:如何在第二次运行时删除旧的反应变量 [英] Dynamically rendered UI: how to delete old reactive variables on second run

查看:149
本文介绍了动态呈现的UI:如何在第二次运行时删除旧的反应变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你的英雄的堆栈溢出,



SHORT SUMMARY:
应用程序运行良好,直到您更改输入输入字段中的数字。 UI重新渲染很好,但服务器端失败,仍然在内存中似乎。详细解释如下:



我有一个很好的工作动态应用程序,但我仍然在处理一些错误和一个核心问题。



问题必须在反应性的某个地方,但我有很多困难,弄清楚我做错了什么。我已经尝试了几十个事情,没有任何工作,或者最终在其他领域打破了应用程序。



以下是主要问题:



应用程序记录用户点击操作在一个名为dynamicvalues_highlight_button_sf1的reactiveValues()列表中为1或0,并且元素在一个重叠功能中动态制作,使得动态观察者与动态按钮的创建方式相同。
当您输入一个数字时,按钮出现,一切正常工作。



UNTIL您更改文本字段中的数字。
- 按钮被更新,新的数量被渲染,等等,
BUT:旧的dynamicvalues_highlight_button_sf1和动态列表仍在打印中。
我很无奈为什么旧的结果还在那里以及新的结果。



所以而不是新的结果:

  [1]dl = 0,0,0,0,1##当前nr元素的状态(这里为5)
[1]ob = 5### nr最后点击的按钮
[1]-----------下一个点击事件打印下面的这行-----------

我得到的打印输出是旧的和新的结果:

  [1]dl = 0,0,0,0,1,0##旧结果
[1]ob = 5
[1]-----------下一个点击事件打印下面这一行-----
[1]dl = 0,0,0,0,0 ,0##新结果
[1]ob = 5
[1]-----------下一个点击事件打印下面这行---- -

我尝试过像 rm(dynamicvalues_highlight_button_sf1) rm(dynamiclist),但是只有在值存在的情况下才可以工作,并且在应用启动时导致崩溃,因为它们没有。如果(exists(dynamicvalues_highlight_button_sf1)){}
doens't



工作因为存在似乎在无效值列表上无效。 (我也试过评估(需要(...变量...,文本)) if(!is.null (...变量...)){...} 但都失败了,也尝试将它们放在服务器的不同位置,但没有成功,我迷失了,我的知识




  • 第二部分问题



如果我首先输入ie 5,点击某些东西,然后重新创建大于5的数字的按钮,即6:BUTTON nr 6作品(获得蓝色等) ),但按钮1:5不起作用。



我怀疑这两个问题是相互关联的。



注意:
- 发布了最小的例子,但它是一个相当复杂的应用程序,以便在这里拥有整体功能
- 真正的应用程序将吐出一个大模型的输入NR在这个演示中,而不是输入字段
- 尽可能注释为了清楚起见
- 我留下了一些最后一次尝试解决server.r中的问题的代码18-25。



感谢您提供的任何帮助!



UI.r

  (闪亮)
库(shinydashboard)
库(ShinyBS)


ui< - dashboardPage(
dashboardHeader(title =My Test App )
dashboardSidebar(
sidebarMenu(id =tabs,menuItem(testpage,tabName =testpage,icon = icon(book))



dashboardBody(
tags $ head(tags $ style(HTML('。skin-blue .content-wrapper,.right-side {background-color:#ffffff;}, ')))


tabItems(

### test page ### _________
tabItem(tabName =testpage,

h5(在此输入所需的元素),
textInput(inputId =NrOfClusters,label = NULL,placeholder =NULL),

fluidRow (
列(2,
uiOutput(buttons_highlight_sf1)),

列(1,
uiOutput(button_hig htlight_all_sf1),
uiOutput(multi_highlight),
br(),
actionButton(inputId =statuscheck,label =status,style =background-color: )
)))))))

SERVER.R

  shinyServer = function(input,output,session){

####### ##########开始功能HOME TAB ############################

###创建2个反应环境列表
值< - reactiveValues()
dynamicvalues_highlight_button_sf1 < - reactiveValues()

###设置两个按钮的初始状态
值$ HL_multi_switch_sf1 < - FALSE
值$ HL_all_switch_sf1 < - FALSE

###如果用户键入值,然后将其转换为此nr $的无效值b $ b observeEvent(输入$ NrOfClusters,{
isolated(values $ nrofelements< - paste0(input $ NrOfClusters))

## TR Y有动态列表和dynamic_highlight_button_sf1中的所有反应元素
if(exists(dynamiclist)){

rm(dynamiclist)
rm(dynamicvalues_highlight_button_sf1)
dynamicvalues_highlight_button_sf1 < - reactiveValues()}

isolation(dynamiclist< - as.character(unlist(reactiveValuesToList(dynamicvalues_highlight_button_sf1),use.names = FALSE)))
isolation(print paste0(dl length =,length(dynamiclist))))
})


#### RENDER DYNAMIC UI and DYNAMIC OBSERVERS
observeEvent $ nrofelements,{
print(values $ nrofelements == 1 |值$ nrofelements> 1)

###创建等于输入值的nr按钮
if(values $ nrofelements == 1 | values $ nrofelements> 1){

输出$ buttons_highlight_sf1< - renderUI({

lapply(1:values $ nrofelements,function(ab){
if(!is.null(dynamicvalues_highlight_button_sf1 [ [paste0(highlight_button,ab)]]))){
if(dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ab)]] == 0){
div(br(),actionButton inputId = paste0(highlight_button_sf1,ab),label = icon(lightbulb-o),style =color:gray;
background-color:white;
height:35px;
width:35px;
text-align:center;
text-highlight_buttonent:0,5px;
border-radius:6px;
显示:块;
margin:auto;
border-width:2px))}
else {div(br(),actionButton(inputId = paste0(highlight_button_sf1,ab),label = icon(lightbulb-o =color:black;
background-color:white;
border-color:blue;
height:35px;
width:35px;
text-align: center;
text-highlight_buttonent:0,5px;
border-radius:6px;
display:block;
margin:auto;
border-width:2px )}}
else {div(br(),actionButton(inputId = paste0(highlight_button_sf1,ab),label = icon(lightbulb-o),style =color:gray;
背景颜色:白色
height:35px;
width:35px;
text-align:center;
text-highlight_buttonent:0,5px;
border-radius:6px;
display:block;
margin:auto;
border-width:2px))}
})
})

###创建一个按钮突出显示所有
输出$ button_hightlight_all_sf1< ; - renderUI({
if(values $ HL_all_switch_sf1 == TRUE){
div(br(),actionButton(inputId =hightlight_all_button_sf1,label =All,style =color:blue;背景颜色:白色),
else {div(br(),actionButton(inputId =hightlight_all_button_sf1,label =All,style =color:白色),br())}
})

###创建一个按钮以启用高亮显示多个或正弦框
输出$ multi_highlight< - renderUI({
if(values $ HL_multi_switch_sf1 == TRUE){
div(br(),actionButton(inputId =multi_highlight,label =multi,style =color:blue; background-color:white ),br())}
else {div(br(),actionButton(inputId =multi_highlight,label =single,styl e =color:green;背景颜色:白色),br())}
})


###在所有动态创建的按钮上循环应用
isolation(lapply 1:value $ nrofelements,function(ob){
observeEvent(input [[paste0(highlight_button_sf1,ob)]],{

###复杂观察器结构来检查什么取决于ALL和MULTI状态
### FALSE all FALSE multi
if(values $ HL_all_switch_sf1 == FALSE){
if(values $ HL_multi_switch_sf1 == FALSE){
for(each in 1:values $ nrofelements){
if(ob!= each){dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,each)]]< - 0}
else if == each){
if(is.null(dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]])){dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]]< - 1}
else if(dynamicvalues_highlight_b utton_sf1 [[paste0(highlight_button,ob)]] == 1){dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]]< - 0}
else if(dynamicvalues_highlight_button_sf1 [[paste0(highlight_button ,ob)]] == 0){dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]]< - 1}
}}}
### FALSE all TRUE multi
if(values $ HL_multi_switch_sf1 == TRUE){
if(is.null(dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]))){dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]] < - 1}
else if(dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]] == 1){dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]]< - 0}
else if(dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]] == 0){dynamicvalues_highlight_button_sf1 [[paste0(highlight_button ,ob]]]< - 1}
}}

### TRUE all TRUE multi
if(values $ HL_all_switch_sf1 == TRUE){
if (值$ HL_multi_switch_sf1 == TRUE){
dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,ob)]]< - 0
isolation(values $ HL_all_switch_sf1 < - FALSE)}
# ## TRUE all FALSE multi
else if(values $ HL_multi_switch_sf1 == FALSE){for(each in 1:values $ nrofelements)
{if(ob!= each){dynamicvalues_highlight_button_sf1 [[paste0( highlight_button,each)]]< - 0}
}
isolated(values $ HL_all_switch_sf1< - FALSE)
}}


dynamiclist < - as.character(unlist(reactiveValuesToList(dynamicvalues_highlight_button_sf1),use.names = FALSE))
print(paste0(dl =,toString(dynamiclist)))

print粘贴(ob =,ob))

lastclicked_button_nr< - ob

colorpalette < - vector(mode =character,length = values $ nrofelements)
colorpalette< - 替换(colorpalette,colorpalette ==,GRAY)
colorpalette [values $ button_nr_clicked] = RED
打印(-----------下一个点击事件打印下面这一行--------------------- -----------------------------------------)
})
}))
}
})


#### OBSERVE DYNAMIC UI

observeEvent(input $ multi_highlight, {
if(values $ HL_multi_switch_sf1 == TRUE){values $ HL_multi_switch_sf1 < - FALSE}
else if(values $ HL_multi_switch_sf1 == FALSE){values $ HL_multi_switch_sf1 < - TRUE}
}



observeEvent(输入$ hightlight_all_button_sf1,{
if(values $ HL_all_switch_sf1 == TRUE){values $ HL_all_switch_sf1< - FALSE}
else if(values $ HL_all_switch_sf1 == FALSE){values $ HL_all_switch_sf1 < - TRUE}


if(values $ HL_all_switch_sf1 == TRUE){for(any in 1:val ues $ nrofelements){dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,any)]]< - 1}}
else if(values $ HL_all_switch_sf1 == FALSE){for(any in 1:values $ nrofelements){ dynamicvalues_highlight_button_sf1 [[paste0(highlight_button,any)]]< - 0}}

colorpalette< - NULL
colorpalette< - vector(mode =character值$ nrofelements)
colorpalette< - 替换(colorpalette,colorpalette ==,RED)

})

###打印多个和全部在控制台上的状态来检查它们是什么
observeEvent(输入$ statuscheck,{
print(paste(ALL switch:,values $ HL_all_switch_sf1))
print (MULTI开关:,值$ HL_multi_switch_sf1))
})
}

其他错误1:
如果您将数字输入更改为无,我们收到错误



其他错误2:
如果我开始进入0它很顺利,我们没有按钮,如果我输入任何高于0的数字,我们得到那么多按钮,但如果我然后将其更改为0按钮,我得到2个按钮:



服务器的第36行中的动态renderUI包含在一个条目中:

  if(values $ nrofelements == 1 |值$ nrofelements> 1){...... 


解决方案

好的,如果你看看 reactiveValues (这里


Hello heroes of Stack overflow,

SHORT SUMMARY: App works great, until you change the entered number in the input field. UI re-renders great, but server side fails on stuff still in the memory it seems. Detailed explanation below:

I have a nicely working dynamic app, but I'm still dealing with a few bugs and one core problem.

The problem must be somewhere in the reactivity but I'm having a lot of difficulty to figure out what it is that Im doing wrong. I've tried dozens of things already, and none of them work, or end up breaking the app in other areas.

Here is the MAIN PROBLEM:

The app records the user click actions as 1's or 0's in a reactiveValues() list called dynamicvalues_highlight_button_sf1 and the elements are dynamically made within an lapply function that makes the dynamic observers the same way the dynamic buttons are made. When you enter a number, buttons appear and everything works perfect

UNTIL you change the number in the text field. -The buttons are updated and new amount is rendered, etc, BUT: the old dynamicvalues_highlight_button_sf1 and dynamiclist is still being printed. I am clueless why the old results are still there as well as new ones.

So instead of just the new results:

[1] "dl = 0, 0, 0, 0, 1" ## status of the current nr of elements (here its 5)
[1] "ob = 5"   ### nr of the last clicked button
[1] "-----------next click event prints the below this line-----------" 

the printout I get is old and new results:

[1] "dl = 0, 0, 0, 0, 1, 0" ## old results
[1] "ob = 5"
[1] "-----------next click event prints the below this line-----"
[1] "dl = 0, 0, 0, 0, 0, 0" ## new results
[1] "ob = 5"
[1] "-----------next click event prints the below this line-----"

I've tried things like rm(dynamicvalues_highlight_button_sf1) and rm(dynamiclist) but those can only work if the values are there, and cause a crash when the app starts since they don't.

Wrapping them inside an if(exists("dynamicvalues_highlight_button_sf1")) { } doens't work because exists seems not to work on reactivevalues lists. (I've also tried evaluate(need(...the variable..., "text")) and if(!is.null(...the variable...)){...} but all failed. Also tried to put these in different places in the server but no succes. I'm lost and my knowledge of R shiny still is too limited for this complexity it seems.

  • SECOND Part of the problem

if I first enter i.e. 5, click something, and then recreate buttons for a number larger than 5 i.e. 6: BUTTON nr 6 works (gets blue etc), but buttons 1:5 DO NOT work.

I suspect the two problems are related to each other.

The UI and server are posted below. Have some fun trying it before you dive into the problem if you like.

NOTES: - posted the "minimal example" but its a rather complex app in order to have the whole functionality here. - the real app will spit the input NR out from a big modeling step rather than the input field in this demo - I annotated as much as possible for clarity - I left a little bit of code of my last attempt to solve the problem in the server.r at lines 18-25.

Thanks for any help you can offer!

UI.r

library(shiny)
library(shinydashboard)
library(shinyBS)


ui <- dashboardPage(
  dashboardHeader(title = "My Test App"),
  dashboardSidebar(
    sidebarMenu(id = "tabs", menuItem("testpage", tabName = "testpage", icon = icon("book"))
    )
  ),

  dashboardBody(
    tags$head(tags$style(HTML('.skin-blue .content-wrapper, .right-side {background-color: #ffffff; }, '))),


        tabItems(

  ### test page ###_________
      tabItem(tabName = "testpage",  

              h5("Enter desired nr of elements here"),
              textInput(inputId ="NrOfClusters", label = NULL , placeholder = "NULL"),

              fluidRow(
                column(2,
                       uiOutput("buttons_highlight_sf1")),

                column(1,
                    uiOutput("button_hightlight_all_sf1"),
                    uiOutput("multi_highlight"),
                    br(),
                    actionButton(inputId = "statuscheck", label = "status", style = "background-color: white")
                ))))))

SERVER.R

shinyServer = function(input, output, session) {

  ################# start functionality HOME TAB #############################  

  ### create 2 reactive environment lists
  values <- reactiveValues()
  dynamicvalues_highlight_button_sf1 <- reactiveValues()

  ### set initial state of two buttons 
  values$HL_multi_switch_sf1 <- FALSE
  values$HL_all_switch_sf1 <- FALSE 

  ### if the user types in a value, then convert it to a reactive value of this nr
  observeEvent (input$NrOfClusters, {
    isolate(values$nrofelements <- paste0(input$NrOfClusters))

    ##TRY THERE TO REMOVE THE dynamiclist and all the reactive elements in dynamic_highlight_button_sf1
    if (exists("dynamiclist")) { 

      rm(dynamiclist)
      rm(dynamicvalues_highlight_button_sf1)
      dynamicvalues_highlight_button_sf1 <- reactiveValues() } 

    isolate( dynamiclist <- as.character(unlist(reactiveValuesToList(dynamicvalues_highlight_button_sf1), use.names = FALSE)))
    isolate( print(paste0("dl length = ", length(dynamiclist))))
    })


#### RENDER DYNAMIC UI and DYNAMIC OBSERVERS
  observeEvent(values$nrofelements, {
   print(values$nrofelements == 1 | values$nrofelements >1)

    ### create a nr of buttons equal to the entered value
    if (values$nrofelements == 1 | values$nrofelements >1) { 

      output$buttons_highlight_sf1 <- renderUI({

        lapply(1:values$nrofelements, function(ab) {
          if (!is.null(dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ab)]])) { 
            if(dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ab)]] == 0 ) {
              div(br(), actionButton(inputId = paste0("highlight_button_sf1", ab), label = icon("lightbulb-o"),style = "color: grey;
                          background-color: white;
                                   height: 35px;
                                   width: 35px;
                                   text-align:center;
                                   text-highlight_buttonent: 0,5px;
                                   border-radius: 6px;
                                   display:block;
                                   margin: auto;
                                   border-width: 2px")) } 
              else { div(br(), actionButton(inputId = paste0("highlight_button_sf1", ab), label = icon("lightbulb-o"),style = "color: black;
                                  background-color: white;
                                  border-color: blue;
                                  height: 35px;
                                  width: 35px;
                                  text-align:center;
                                  text-highlight_buttonent: 0,5px;
                                  border-radius: 6px;
                                  display:block;
                                  margin: auto;
                                  border-width: 2px"))  }  }
              else { div(br(), actionButton(inputId = paste0("highlight_button_sf1", ab), label = icon("lightbulb-o"),style = "color: grey;
                                  background-color: white; 
                                  height: 35px; 
                                  width: 35px;
                                  text-align:center;
                                  text-highlight_buttonent: 0,5px;
                                  border-radius: 6px;
                                  display:block;
                                  margin: auto;
                                  border-width: 2px")) } 
            })
      })

      ### create a button to highlight all
      output$button_hightlight_all_sf1 <- renderUI({ 
        if(values$HL_all_switch_sf1 == TRUE) { 
        div( br(), actionButton(inputId = "hightlight_all_button_sf1", label = "All", style = "color: blue; background-color:white"), br())}
        else { div( br(), actionButton(inputId = "hightlight_all_button_sf1", label ="All", style = "color: grey; background-color:white"), br())}
      })

     ### create a button to enable highlight multiple or sinle boxes
       output$multi_highlight <-  renderUI({
        if(values$HL_multi_switch_sf1 == TRUE) { 
          div( br(), actionButton(inputId = "multi_highlight", label ="multi", style = "color: blue; background-color:white"), br())}
         else { div( br(), actionButton(inputId = "multi_highlight", label ="single", style = "color: green; background-color:white"), br())}
         })


    ### loop apply function over all dynamically created buttons
    isolate(lapply(1:values$nrofelements,  function(ob) {
      observeEvent(input[[paste0("highlight_button_sf1", ob)]], {

    ### complex observer structure to check what to do depending on the ALL and MULTI status
    ### FALSE all FALSE multi 
    if (values$HL_all_switch_sf1 == FALSE) {
            if (values$HL_multi_switch_sf1 == FALSE) { 
                for (each in 1:values$nrofelements) { 
                  if ( ob != each) { dynamicvalues_highlight_button_sf1[[paste0("highlight_button", each)]] <- 0}
                  else if (ob == each) { 
                        if (is.null(dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]])) {dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] <- 1}
                        else if (dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] == 1) {dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] <- 0}
                        else if (dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] == 0) {dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] <- 1}
                  }}}
      ### FALSE all TRUE multi
            if (values$HL_multi_switch_sf1 == TRUE){
                        if (is.null(dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]])) {dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] <- 1}
                        else if (dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] == 1) {dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] <- 0}
                        else if (dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] == 0) {dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] <- 1}
            }}

    ### TRUE all TRUE multi
    if(values$HL_all_switch_sf1 == TRUE) { 
            if (values$HL_multi_switch_sf1 == TRUE) {
              dynamicvalues_highlight_button_sf1[[paste0("highlight_button", ob)]] <- 0
              isolate(values$HL_all_switch_sf1 <- FALSE)}
    ### TRUE all FALSE multi
    else if (values$HL_multi_switch_sf1 == FALSE) { for (each in 1:values$nrofelements) 
        {if (ob != each) { dynamicvalues_highlight_button_sf1[[paste0("highlight_button", each)]] <- 0}
        }
             isolate(values$HL_all_switch_sf1 <- FALSE)
    }}


      dynamiclist <- as.character(unlist(reactiveValuesToList(dynamicvalues_highlight_button_sf1), use.names = FALSE))
      print(paste0("dl = ", toString(dynamiclist)))

        print(paste("ob =", ob ))

        lastclicked_button_nr <- ob

        colorpalette <- vector(mode="character", length=values$nrofelements)
        colorpalette <- replace(colorpalette, colorpalette == "", "GREY")
        colorpalette[values$button_nr_clicked]="RED"
        print( "-----------next click event prints the below this line--------------------------------------------------------------")
      })
      }))
      }
      })


#### OBSERVE DYNAMIC UI

observeEvent(input$multi_highlight, { 
  if (values$HL_multi_switch_sf1 == TRUE) { values$HL_multi_switch_sf1 <- FALSE }
  else if (values$HL_multi_switch_sf1 == FALSE) { values$HL_multi_switch_sf1 <- TRUE }
})



observeEvent(input$hightlight_all_button_sf1,{
  if (values$HL_all_switch_sf1 == TRUE) { values$HL_all_switch_sf1 <- FALSE }
  else if (values$HL_all_switch_sf1 == FALSE) {values$HL_all_switch_sf1 <- TRUE}


  if (values$HL_all_switch_sf1 == TRUE) { for (any in 1:values$nrofelements) { dynamicvalues_highlight_button_sf1[[paste0("highlight_button", any)]] <- 1}}
  else if (values$HL_all_switch_sf1 == FALSE) { for (any in 1:values$nrofelements) { dynamicvalues_highlight_button_sf1[[paste0("highlight_button", any)]] <- 0}}

  colorpalette <- NULL
  colorpalette <- vector(mode="character", length=values$nrofelements)
  colorpalette <- replace(colorpalette, colorpalette == "", "RED")

})

### button to print the status of Multi and All on console to check what they are
observeEvent(input$statuscheck, { 
  print(paste("ALL switch: ", values$HL_all_switch_sf1)) 
  print(paste("MULTI switch: ", values$HL_multi_switch_sf1)) 
  })
}

additional bug 1: if you change the numberinput to nothing we get an error

additional bug 2: if I start with entering "0" it goes well and we get no buttons, if I enter any number higher than 0 we get that many buttons, but if I then change it to 0 buttons I get 2 buttons!:

eventough the dynamic renderUI in line 36 of the server is wrapped inside a condtion:

if (values$nrofelements == 1 | values$nrofelements >1) { ...... 

解决方案

Okay, your problem is a tricky one that people have fallen for before, if you look at the documentation of reactiveValues (here reactiveValues docs) it says that

"Note that values taken from the reactiveValues object are reactive, but the reactiveValues object itself is not."

So you should not be using dynamicvalues_highlight_button_sf1 the way your are, you should be using named elements of it. I got it to work by doing the following:

  • replacing dynamicvalues_highlight_button_sf1 with dhbs globally (not necssary but the lines were getting way too long for me to see what was going on).
  • replacing dhbs with dhbs$el globally.
  • getting rid of all the reactiveValuesToList calls.
  • getting rid of all the attempts to rm(...) things out of the reactive environment.
  • adding a dhbs$el <- NULL statement as the first line of the observeEvent(values$nrofelements, { node code.
  • added an extra output field to inspect dhbs with a renderTextVerbatum statement. This is a useful debugging technique when you get used to it.
  • eliminated a lot of redundant code.
  • eliminated all the isolate statements which were not doing anything.
  • added a clickcount to handle the reactivity better.

Seems to work now, although there might be a few other problems to fix up still as a result of those changes. I also think that many of those isolates are probably unnecessary and just a result of your debugging activities.

The code:

library(shiny)
library(shinydashboard)
library(shinyBS)


ui <- dashboardPage(
  dashboardHeader(title = "My Test App"),
  dashboardSidebar(
    sidebarMenu(id = "tabs", menuItem("testpage", tabName = "testpage", icon = icon("book"))
    )
  ),

  dashboardBody(
    tags$head(tags$style(HTML('.skin-blue .content-wrapper, .right-side {background-color: #ffffff; }, '))),


    tabItems(

      ### test page ###_________
      tabItem(tabName = "testpage",  

              h5("Enter desired nr of elements here"),
              textInput(inputId ="NrOfClusters", label = NULL , placeholder = "NULL"),
              verbatimTextOutput("values"),
              verbatimTextOutput("clickcount"),

              fluidRow(
                column(2,
                       uiOutput("buttons_highlight_sf1")),

                column(1,
                       uiOutput("button_hightlight_all_sf1"),
                       uiOutput("multi_highlight"),
                       br(),
                       actionButton(inputId = "statuscheck", label = "status", style = "background-color: white")
                ))))))

off_style <- 
"color: grey;
background-color: white;
height: 35px;
width: 35px;
text-align:center;
text-highlight_buttonent: 0,5px;
border-radius: 6px;
display:block;
margin: auto;
border-width: 2px"

on_style <- 
"color: grey;
background-color: white;
border-color: blue;
height: 35px;
width: 35px;
text-align:center;
text-highlight_buttonent: 0,5px;
border-radius: 6px;
display:block;
margin: auto;
border-width: 2px"


shinyServer = function(input, output, session) {

  ################# start functionality HOME TAB #############################  

  ### create 2 reactive environment lists
  values <- reactiveValues(clickcount=0)
  dhbs <- reactiveValues(el=NULL)

  ### set initial state of two buttons 
  values$HL_multi_switch_sf1 <- FALSE
  values$HL_all_switch_sf1 <- FALSE 

  ### if the user types in a value, then convert it to a reactive value of this nr
  observeEvent (input$NrOfClusters, {
    values$nrofelements <- input$NrOfClusters
    dynamiclist <- as.character(unlist(dhbs$el), use.names = FALSE)
    print(paste0("dl length = ", length(dynamiclist)))
  })

  hibutname <- function(idx){
    sprintf("highlight_button_sf1-%s-%d",values$nrofelements,idx)
  }
  atbutname <- function(idx){
    sprintf("activate_button_sf1-%s-%d",values$nrofelements,idx)
  }
  fliphib <- function(idx){
    hib <- hibutname(idx)
    dhbs$el[hib] <- abs(1-dhbs$el[hib])
  }

  sethib <- function(idx,v){
    hib <- hibutname(idx)
    dhbs$el[hib] <- v
  }


  #### RENDER DYNAMIC UI and DYNAMIC OBSERVERS
  observeEvent(values$nrofelements, {
    req(input$NrOfClusters)
    nel <- values$nrofelements
    dhbs$el <- rep(0,nel) 
    names(dhbs$el) <- sapply(1:nel,hibutname)
    print(names(dhbs$el))

    output$buttons_highlight_sf1 <- renderUI({
      values$clickcount
      print("clickcount")
      print(values$clickcount)
      lapply(1:values$nrofelements, function(ab) {
          if(dhbs$el[[hibutname(ab)]] == 0 ) {
            print("gray")
            div(br(), actionButton(inputId = hibutname(ab), label = icon("lightbulb-o"),style = off_style)) 
          } else { 
            print("black")
            div(br(), actionButton(inputId = hibutname(ab), label = icon("lightbulb-o"),style = on_style))  
          }  
      })
    })

    ### create a button to highlight all
    output$button_hightlight_all_sf1 <- renderUI({ 
      if(values$HL_all_switch_sf1 == TRUE) { 
        div( br(), actionButton(inputId = "hightlight_all_button_sf1", label = "All", style = "color: blue; background-color:white"), br())
      } else { 
        div( br(), actionButton(inputId = "hightlight_all_button_sf1", label ="All", style = "color: grey; background-color:white"), br())
      }
    })

    ### create a button to enable highlight multiple or single boxes
    output$multi_highlight <-  renderUI({
      if(values$HL_multi_switch_sf1 == TRUE) { 
        div( br(), actionButton(inputId = "multi_highlight", label ="multi", style = "color: blue; background-color:white"), br())
      }  else { 
        div( br(), actionButton(inputId = "multi_highlight", label ="single", style = "color: green; background-color:white"), br())
      }
    })


    lapply(1:values$nrofelements,  function(ob) {
      butname <- hibutname(ob)
      observeEvent(input[[butname]], {
        hibut <- hibutname(ob)
        print(hibut)
        values$clickcount <- values$clickcount+1
        print("clicked")
        print(values$clickcount)

        ### complex observer structure to check what to do depending on the ALL and MULTI status
        ### FALSE all FALSE multi 
        if (values$HL_all_switch_sf1 == FALSE) {
          if (values$HL_multi_switch_sf1 == FALSE) { 
            for (each in 1:values$nrofelements) { 
              if ( ob != each) { 
                sethib(each,0) 
              } else { 
                fliphib(each) 
              }
            }
          }
          ### FALSE all TRUE multi
          if (values$HL_multi_switch_sf1 == TRUE){
            fliphib(ob)
          }
        }

        ### TRUE all TRUE multi
        if(values$HL_all_switch_sf1 == TRUE) { 
          if (values$HL_multi_switch_sf1 == TRUE) {
            sethib(ob,0)
            values$HL_all_switch_sf1 <- FALSE
          }
          ### TRUE all FALSE multi
          else if (values$HL_multi_switch_sf1 == FALSE) { 
            for (each in 1:values$nrofelements) {
              if (ob != each) { sethib(each,0) }
            }
            values$HL_all_switch_sf1 <- FALSE
          }
        }


        dynamiclist <- as.character(unlist(dhbs$el), use.names = FALSE)
        print(paste0("dl = ", toString(dynamiclist)))

        print(paste("ob =", ob ))

        lastclicked_button_nr <- ob

        colorpalette <- vector(mode="character", length=values$nrofelements)
        colorpalette <- replace(colorpalette, colorpalette == "", "GREY")
        colorpalette[values$button_nr_clicked]="RED"
        print( "-----------next click event prints the below this line--------------------------------------------------------------")
      })
    })
  })


  #### OBSERVE DYNAMIC UI

  observeEvent(input$multi_highlight, {   values$HL_multi_switch_sf1 <- !values$HL_multi_switch_sf1 })




  observeEvent(input$hightlight_all_button_sf1,{
    values$HL_all_switch_sf1 <- !values$HL_all_switch_sf1;

    for (any in 1:values$nrofelements) { dhbs$el[[hibutname(any)]] <- as.integer(values$HL_all_switch_sf1) }

    colorpalette <- NULL
    colorpalette <- vector(mode="character", length=values$nrofelements)
    colorpalette <- replace(colorpalette, colorpalette == "", "RED")

  })

  ### button to print the status of Multi and All on console to check what they are
  observeEvent(input$statuscheck, { 
    print(paste("ALL switch: ", values$HL_all_switch_sf1)) 
    print(paste("MULTI switch: ", values$HL_multi_switch_sf1)) 
  })

  output$values <- renderPrint(as.character(unlist(dhbs$el), use.names = FALSE))
  output$clickcount <- renderPrint(values$clickcount)
}
options(shiny.reactlog = TRUE)
shinyApp(ui,shinyServer)

Screenshot:

这篇关于动态呈现的UI:如何在第二次运行时删除旧的反应变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆