observeEvent in insertUI erzeugt in Schleifen

stimmen
0

Wenn ich schaffen neue Objekte mit insertUI in einer reaktiven Art und Weise, alle Beobachter, dass ich Arbeit völlig in Ordnung schaffen, wie Sie in der folgenden Blindkode sehen können:

library(shiny)

# Define the UI
ui <- fluidPage(
  actionButton(adder, Add),
  tags$div(id = 'placeholder')
)


# Define the server code
server <- function(input, output) {
  rv <- reactiveValues()

  rv$counter <- 0

  observeEvent(input$adder,{
    rv$counter <- rv$counter + 1

    add <- sprintf(%03d,rv$counter)

    filterId <- paste0('adder_', add)
    divId <- paste0('adder_div_', add)
    elementFilterId <- paste0('adder_object_', add)
    removeFilterId <- paste0('remover_', add)

    insertUI(
      selector = '#placeholder',
      ui = tags$div(
        id = divId,
        actionButton(removeFilterId, label = Remove filter, style = float: right;),
        textInput(elementFilterId, label = paste0(Introduce text #,rv$counter), value = )
      )
    )

    # Observer that removes a filter
    observeEvent(input[[removeFilterId]],{
      removeUI(selector = paste0(#, divId))
    })
  })
}

# Return a Shiny app object
shinyApp(ui = ui, server = server, options = list(launch.browser = T))

Allerdings, wenn ich die gleichen Objekte mit einem for-Schleife erstellen, nur die Beobachter des letzten Objekts geschaffen scheinen zu funktionieren, wie Sie im Beispiel unten sehen können:

library(shiny)

# Define the UI
ui <- fluidPage(
  #actionButton(adder, Add),
  tags$div(id = 'placeholder')
)


# Define the server code
server <- function(input, output) {
  rv <- reactiveValues()

  rv$counter <- 0
  rv$init <- T

  observeEvent(rv$init, {
    if(!rv$init) return(NULL)

    rv$init <- F

    for(i in 1:3) {
      rv$counter <- rv$counter + 1

      add <- sprintf(%03d,rv$counter)

      #prefix <- generateRandomString(1,20)
      filterId <- paste0('adder_', add)
      divId <- paste0('adder_div_', add)
      elementFilterId <- paste0('adder_object_', add)
      removeFilterId <- paste0('remover_', add)

      insertUI(
        selector = '#placeholder',
        ui = tags$div(
          id = divId,
          actionButton(removeFilterId, label = Remove filter, style = float: right;),
          textInput(elementFilterId, label = paste0(Introduce text #,rv$counter), value = )
        )
      )

      # Observer that removes a filter
      observeEvent(input[[removeFilterId]],{
        removeUI(selector = paste0(#, divId))
      })
    }
  })
}

# Return a Shiny app object
shinyApp(ui = ui, server = server, options = list(launch.browser = T))

Was mache ich falsch?

Kann es zu faul Auswertung zusammenhängen?

Veröffentlicht am 20/10/2018 um 12:36
quelle vom benutzer
In anderen Sprachen...                            


2 antworten

stimmen
1

Für Schleifen in R alle im gleichen Umfang laufen, die eine Variable in der Schleife definiert, bedeuten, wird von allen Iterationen geteilt werden. Dies ist ein Problem, wenn Sie eine Funktion in jeder Schleife Iteration erstellen, die diese Variable zugreift, und gehen davon aus, dass es für jede Iteration einzigartig sein wird.

Hier ist eine einfache Demo:

counter <- 0; funcs <- list()
for (i in 1:3) {
    counter <- counter + 1
    funcs[[i]] <- function() print(counter)
}
for (i in 1:3) {
    funcs[[i]]()  # prints 3 3 3
}

In diesem Shiny App, die observeEventgreift Handler die lokale Variable add, und erst nach der for - Schleife ist über genannt bekommt, und addist an seinem Endwert.

Es gibt ein paar Möglichkeiten , um diese und schaffen einen einzigartigen Rahmen für jede Schleife Iteration zu erhalten. Mein Favorit ist eine verwenden applyFunktion der for - Schleife zu ersetzen. Dann wird jede applyIteration läuft in seiner eigenen Funktion so lokale Variablen sind jedes Element einzigartig.

library(shiny)

# Define the UI
ui <- fluidPage(
  #actionButton("adder", "Add"),
  tags$div(id = 'placeholder')
)


# Define the server code
server <- function(input, output) {
  rv <- reactiveValues(counter = 0)

  lapply(1:3, function(i) {
    isolate({
      rv$counter <- rv$counter + 1

      add <- sprintf("%03d",rv$counter)

      #prefix <- generateRandomString(1,20)
      filterId <- paste0('adder_', add)
      divId <- paste0('adder_div_', add)
      elementFilterId <- paste0('adder_object_', add)
      removeFilterId <- paste0('remover_', add)

      insertUI(
        selector = '#placeholder',
        ui = tags$div(
          id = divId,
          actionButton(removeFilterId, label = "Remove filter", style = "float: right;"),
          textInput(elementFilterId, label = paste0("Introduce text #",rv$counter), value = "")
        )
      )
    })

    # Observer that removes a filter
    observeEvent(input[[removeFilterId]],{
      removeUI(selector = paste0("#", divId))
    })
  })
}

# Return a Shiny app object
shinyApp(ui = ui, server = server, options = list(launch.browser = T))

Beachten Sie, dass ich auch die äußere entfernt , observeEventda die Server - Funktion ohnehin auf der Initialisierung der Session läuft.

Beantwortet am 20/10/2018 um 23:56
quelle vom benutzer

stimmen
0

Ich habe eine Abhilfe gefunden, aber ich denke, es sollte auf eine effizientere Art und Weise durchgeführt werden.

Es sieht aus wie dieses Problem zu faul Auswertung verbunden ist, so dass nur das letzte Objekt erstellt hat seine observeEvent Arbeiten. Daher habe ich beschlossen, für jede Iteration der Schleife neue Variablen zu erstellen, mit eval:

library(shiny)

# Define the UI
ui <- fluidPage(
  #actionButton("adder", "Add"),
  tags$div(id = 'placeholder')
)


# Define the server code
server <- function(input, output, session) {
  rv <- reactiveValues()

  rv$counter <- 0
  rv$init <- T

  observeEvent(rv$init, {
    if(!rv$init) return(NULL)

    for(i in 1:4) {
      rv$counter <- rv$counter + 1

      add <- sprintf("%03d",rv$counter)

      coding <- paste0(
        "divId",add," <- paste0('adder_div_', add);
        elementFilterId",add," <- paste0('adder_object_', add);
        removeFilterId",add," <- paste0('remover_', add);
        insertUI(
          selector = '#placeholder',
          ui = tags$div(
            id = divId",add,",
            actionButton(inputId=removeFilterId",add,", label = \"Remove filter\", style = \"float: right;\"),
            textInput(inputId=elementFilterId",add,", label = paste0(\"Introduce text #\",rv$counter), value = '')
          )
        );

        # Observer that removes a filter
        observeEvent(input[[removeFilterId",add,"]],{
          removeUI(selector = paste0(\"#\", divId",add,"))
        })
        "
      )

      eval(parse(text=coding))
    }

    rv$init <- F
  })
}

# Return a Shiny app object
shinyApp(ui = ui, server = server, options = list(launch.browser = T))

Wie es neue Variablen zu sehen ist, hat jede Schleife, so dass das lazy-Auswertung Problem gelöst ist.

Was ich möchte, ist jetzt, wenn es in einer effizienteren Weise getan werden kann.

Beantwortet am 20/10/2018 um 15:02
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more