2016-08-09 2 views
2

사용자가 데이터 테이블에서 시작하여 이전 테이블의 선택된 필터/요약을 기반으로 새 테이블을 만들 수있는 Shiny 앱에서 작업하고 있습니다. R에 목록의 목록을 사용하여R Shiny의 actionButtons를 사용하여 트리에 노드 추가

Table1 ---- (filter) > Table2 
     ---- (filter) > Table3 ---- (filter) > Table4 
           ---- (filter) > Table5 
     ---- (filter) > Table6 

, 나는 각 테이블/노드를 추적 할 (내 코드 예제에서 sliceBox.tree라고도 함) 트리 데이터 구조를 만들었다. 각 테이블에는 일련의 입력도 포함됩니다. 일부 필터 설정과 actionButton은 해당 상위 테이블 아래에 새 하위 테이블을 만드는 데 사용할 수 있습니다.

각 단추 누르기에 반응하기 위해 observeEvent() 함수를 사용하고 있지만 observeEvent 핸들러 내에서 트리에 노드를 추가하려고하면 변경 내용이 함수 내부의 복사 트리에만 적용됩니다. 원래 나무는 영향을받지 않습니다. observeEvent 핸들러 내부에서 원래 트리를 편집하는 방법이 있습니까? 아니면 이렇게하려면 다른 방법일까요?

여기에 문제를 설명하기 위해 자른 코드의 트리밍 된 버전이 있습니다. 현재 코드가 기존 버튼을 클릭하여 페이지에서 하위 actionButton을 생성하기를 원합니다. 일이에 갇혀 -

server <- function(input, output) { 

    newNode <- function(id, parentId) { 
    node <- list(
     parent = parentId, 
     children = list(), 
     uiObject = createButton(id, parentId) 
    ) 
    return(node) 
    } 


    createButton <- function(id, parentId) { 
    print(paste0("Creating button ", id)) 
    buttonID <- paste0("sliceBoxButton", id) 
    return(actionButton(buttonID, paste0("I am ", buttonID, ", child of ", parentId), icon("plus-circle fa-2x"))) 
    } 


    rootNode <- newNode(1, 0) 
    sliceBox.tree <- list(rootNode) # We'll store our nodes as a 1D list, so parent and child ID's are recorded as their indices in the list 
    output$debug <- renderPrint({ 
    print(paste0("Button presses: ", v$counter)) 
    print("FULL TREE") 
    print(sliceBox.tree) 
    }) 


    # Keep a total count of all the button presses (also used loosely as the number of tables created) 
    v <- reactiveValues(counter = 1L) 

    # Event handlers: specific function for particular button will run when that button is pressed 
    observeEvent(v$counter, { 
    for (id in 1:v$counter) { 
     buttonID <- paste0("sliceBoxButton", id) 
     observeEvent(input[[buttonID]], { 
     v$counter <- v$counter + 1L 
     print(paste0("Pressed ", buttonID)) 


     # Append new child to list of children 
     numChildren <- length(sliceBox.tree[[id]]$children) 
     sliceBox.tree[[id]]$children[numChildren + 1] <- v$counter 


     sliceBox.tree[[v$counter]] <- newNode(v$counter, id) 
     print(paste0("Appending node to tree at index ", v$counter)) 
     print(sliceBox.tree) 
     }) 
    } 
    }) 


    # renderUI needs a list of uiObjects, so we just extract the uiObjects from every node of the tree 
    output$allSliceBoxes <- renderUI({ 
    table_output_list <- lapply(1:v$counter, function(i) { 
     return(getElement(sliceBox.tree[[i]], 'uiObject')) 
    }) 
    do.call(tagList, table_output_list) # Convert the list to a tagList 
    }) 


} 


ui <- fluidPage(
    uiOutput("allSliceBoxes"), 
    verbatimTextOutput('debug') 
) 


shinyApp(ui = ui, server = server) 

는 정말 광범위하게 인터넷 검색을 봤는데하지만 비슷한 할 예제를 발견하지 않았습니다, 누군가가 도와 수 있기를 바랍니다!

답변

1

이 문제를 해결하는 한 가지 방법은 귀하의 트리를 reactiveValues ​​구조에 저장하는 것입니다. 그 시점에서

# sliceBox.tree <- list(rootNode) 
# Use this instead: 
sliceBox.tree <- reactiveValues(tree=list(rootNode)) 

, 모든 sliceBox.tree sliceBox.tree$tree에 변경합니다. 그것은 나를 위해 작동합니다.

관련 문제