2015-01-12 44 views
1

我正在寫一個Shinyapp,使用戶能夠將新條目輸入到MongoDB中,並從中刪除特定的行。爲什麼我使用不同的actionLink後,我的Shiny(R)actionButton沒有響應?

我想添加一個功能,可以通過保存行的臨時副本來撤消上次刪除。它似乎工作正常,但在使用撤消之後,出於某種原因,刪除按鈕不起作用了,我不知道爲什麼。

我想也許它有一些事實,有一些其他地方,我使用觀察員的兩個按鈕,但我不明白爲什麼會導致任何問題(我需要他們的應用程序以正常工作) - 無論如何,他們不會阻止我逐一刪除多行,只要我不使用undo功能。你可以從下面的代碼中看到,我已經在其中加入了一堆print()函數來試圖找出它的前進方向。奇怪的是 - 他們都沒有出現!就好像刪除按鈕根本不會在撤消使用後激活腳本。任何想法爲什麼?

UPDATE:下面是重現問題(不使用的MongoDB)server.R和ui.R短版:

server.R

tempEntry<-NULL 
shinyServer(function(input, output, session) { 
    dat<-data.frame(nums=1:3,ltrs=c("a","b","c")) 
    ## Action: Delete entry 
    output$delError<-renderText({ 
     input$delButton 
     isolate({if (!is.na(input$delNum)) { 
      tempEntry<<-dat[input$delNum,] 
      output$undo<<-renderUI({ 
       actionLink("undo","Undo last delete") 
       }) 
      dat<<-dat[-input$delNum,] 
      print("deleted") 
      print(dat) 
     } else print("nope2") 
     }) 
    }) 

    ## Action: Undo delete 
    output$undoError<-renderText({ 
     input$undo 
     if (!is.null(input$undo)) { 
     if (input$undo>0) { 
     isolate({if (!is.null(tempEntry)) { 
      dat<<-rbind(dat,tempEntry) 
      tempEntry<<-NULL 
      output$delError<<-renderText({""}) 
      print(dat) 
     } else print("nope3") 
     }) } else print("undo==0") } else print("undo null") 
    }) 
}) 

ui.R:

library(shiny) 
shinyUI(navbarPage("example", 
        tabPanel("moo", 
        titlePanel(""), 
        fluidPage(numericInput("delNum","Row to delete",value=NULL), 
          actionButton("delButton","Delete row"), 
          uiOutput("undo"), 
          div(p(textOutput("delError")),style="color:red"), 
          div(p(textOutput("undoError")),style="color:blue") 
          ))))   

(這也給出了一個錯誤「參數1(類型'列表')不能由'貓'處理刪除一行後,我不知道爲什麼......但問題不是似乎與此有關)。

謝謝!

+1

你可以給爲重現此問題儘可能小的'server.R'和'ui.R'文件? –

+0

嗨Marat,感謝評論。我編輯了我的問題,以包含一個短版本的server.R和ui.R,它重現了這個問題。 – doviod

回答

0

發生這種情況的原因是由於output$delError<<-renderText({""})代碼覆蓋原來的空白表達式output$delError,因此output$delError不會在input$delButton上再次觸發。


[更新]

的OP的應用程序使用actionButtonactionLink從數據庫中刪除分別取消刪除和記錄。 '刪除'按鈕應該觸發delError表達式,刪除記錄並顯示刪除的結果(例如'記錄已刪除')。同樣,「取消刪除」按鈕會觸發undoError表達式,該記錄會將記錄放回表中並報告取消刪除的結果(例如,'記錄未刪除')。問題是,undoError必須擺脫由delError產生的輸出,因爲輸出'記錄刪除'和'記錄未刪除'在它們一起出現時沒有太大意義,但輸出'刪除記錄'只能通過delError的表達。

似乎可以通過修改delError來解決此問題,以便在按下「取消刪除」按鈕(或鏈接)時隱藏其輸出。但在這種情況下,delError會在'刪除'和'取消刪除'按鈕上觸發,而不能說出哪個按鈕導致評估,所以當按下'取消刪除'按鈕時它會嘗試刪除記錄!

下面的示例應用程序提供了一種通過使用存儲最後一個操作的狀態的全局變量來解決此問題的方法。這種狀態是由兩個高優先級的觀察者(一個用於「刪除」,另一個用於「取消刪除」)生成的,它還負責實際刪除/刪除記錄。觀察者不會產生直接進入網頁的輸出,所以沒有擺脫其他觀察者產生的消息的麻煩。相反,狀態變量通過簡單的反應式表達式顯示。

server.R

tempEntry<-NULL 
dat<-data.frame(nums=1:3,ltrs=c("a","b","c")) 


shinyServer(function(input, output, session) { 

    del.status <- NULL 


    ################## 
    ### Observers #### 
    ################## 

    delete.row <- observe({ 
     if (input$delButton ==0) return() # we don't want to delete anything at start 

     delNum <- isolate(input$delNum) # this is the only thing that needs to be isolated 
     if (is.na(delNum)) { 
      print('nope2') 
      return() 
     } 

     tempEntry <<- dat[delNum,] 
     dat <<- dat[-delNum,] 

     output$undo <<- renderUI(actionLink("undo","Undo last delete")) 
     del.status <<- 'deleted' 
    },priority=100) # make sure that del.status will be updated *before* the evaluation of output$delError 



    undelete.row <- observe({ 
     if (is.null(input$undo) || input$undo==0) return() # trigger on undowe don't want to undelete anything at the beginning of the script 

     dat <<- rbind(dat,tempEntry) 
     tempEntry <<- NULL 

     output$undo <<- renderUI("") 
     del.status <<- 'undeleted' 
    },priority=100) 



    ################## 
    ### Renderers #### 
    ################## 

    output$delError <- renderText({ 
     if (input$delButton == 0) return() # show nothing until first deletion 
     input$undo       # trigger on undo 

     return(del.status) 
    }) 

    output$show.table <- renderTable({ 
     input$delButton; input$undo  # trigger on delete/undelete buttons 
     return(dat) 
    }) 

}) 

ui.R

library(shiny) 
shinyUI(
    navbarPage(
     "example" 
     , tabPanel("moo" 
     , titlePanel("") 
     , fluidPage(
      numericInput("delNum","Row to delete",value=NULL) 
      , div(p(textOutput("delError")),style="color:red") 
      , actionButton("delButton","Delete row") 
      , uiOutput("undo") 
      , tableOutput('show.table') 
      ) 
     ) 
    ) 
) 
+0

我認爲任何包含被激活的無功元素的聲明都會被觸發。畢竟 - 輸出$ delError以NULL開始,並且在我調用輸入$ delButton之前沒有任何東西... 如何實現我的目標(一旦發生撤消操作就從delError中移除消息)而不會導致這個? – doviod

+0

@dovoid,'output $ delError' *在開始時返回*'NULL',但它可以觸發'input $ delButton'並返回不同的東西。在輸出$ delError << - renderText({「」})後,它自己變成NULL,因此不能再對輸入$ delButton做出反應。關於你從delError中刪除消息的問題 - 我需要考慮一下... –

+0

但是等待,我沒有傳遞NULL,我將它傳遞給了rendertext({「」})。我在其他多個地方都沒有問題。我可以使_return_ NULL沒有**使它** NULL? – doviod

相關問題