2016-08-09 4 views
2

Ich arbeite an einer Shiny-App, bei der Benutzer von einer Datentabelle aus starten und basierend auf ausgewählten Filtern/Zusammenfassungen der vorherigen Tabellen neue Tabellen erstellen können.Verwenden von R Shinys actionButtons zum Hinzufügen von Knoten zu einem Baum

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

Listen von Listen in R Verwenden habe ich eine Datenstruktur Baum (sliceBox.tree in meinem Codebeispiel genannt) Track jeder Tabelle/Knoten zu halten. Jede Tabelle enthält auch eine Reihe von Eingaben: einige Filtereinstellungen und einen actionButton, mit dem eine neue Kindtabelle unter dieser Elterntabelle erstellt werden kann.

Ich benutze die Funktion observeEvent(), um auf jeden Tastendruck zu reagieren, aber wenn ich versuche, einen Knoten an den Baum innerhalb des Handlers von observeEvent anzuhängen, werden die Änderungen nur an den Kopierbaum innerhalb der Funktion vorgenommen Der ursprüngliche Baum ist davon nicht betroffen. Gibt es eine Möglichkeit, den Originalbaum aus dem Handler "observeEvent" heraus zu bearbeiten oder einen anderen Ansatz dafür?

Hier ist eine abgespeckte Version meines Codes jetzt, um das Problem zu veranschaulichen - Ich möchte den aktuellen Code Kind Aktionsbuttons auf der Seite erstellen, indem Sie auf vorhandene Schaltflächen klicken.

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) 

hoffe wirklich, jemand helfen kann, habe ich habe ausführlich worden googeln aber keine Beispiele gefunden, die ähnliche etwas tun - auf diesem für Tage aufgeklebt!

Antwort

1

Eine Möglichkeit, dies zu lösen, wäre, Ihren Baum in einer reactiveValues-Struktur zu speichern.

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

Von diesem Punkt an, jeden sliceBox.tree-sliceBox.tree$tree ändern. Es funktioniert für mich.

Verwandte Themen