observeEvent σε insertUI παράγεται στο βρόχο

ψήφοι
0

Όταν δημιουργήσετε νέα αντικείμενα με insertUI σε ένα αντιδραστικό τρόπο, όλοι οι παρατηρητές που έχω δημιουργήσει το έργο απολύτως εντάξει, όπως μπορείτε να δείτε στο παρακάτω εικονική κωδικό:

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))

Ωστόσο, αν μπορώ να δημιουργήσω τα ίδια αντικείμενα με τη χρήση ενός βρόχου for, μόνο οι παρατηρητές του τελευταίου αντικειμένου που δημιουργήθηκε φαίνεται να λειτουργεί, όπως μπορείτε να δείτε στο παρακάτω παράδειγμα:

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))

Τι κάνω λάθος?

Μπορεί να σχετίζεται με τεμπέληδες αξιολόγηση;

Δημοσιεύθηκε 20/10/2018 στις 12:36
πηγή χρήστη
Σε άλλες γλώσσες...                            


2 απαντήσεις

ψήφοι
1

Για βρόχων σε R όλα τρέχουν στο ίδιο πεδίο εφαρμογής, το οποίο σημαίνει μια μεταβλητή που ορίζεται στο βρόχο θα μοιράζονται όλοι οι επαναλήψεις. Αυτό είναι ένα θέμα εάν δημιουργήσετε μια συνάρτηση σε κάθε επανάληψη του βρόχου που έχει πρόσβαση αυτή τη μεταβλητή, και να υποθέσουμε ότι αυτό θα είναι μοναδικό για κάθε επανάληψη.

Εδώ είναι ένα απλό 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
}

Σε αυτό το γυαλιστερό app, ο observeEventχειριστής έχει πρόσβαση στην τοπική μεταβλητή add, και δεν παίρνει ονομάζεται μετά ο βρόχος for είναι πάνω, και addείναι στην τελική τιμή του.

Υπάρχουν μερικοί τρόποι για να πάρει γύρω από αυτό και να δημιουργήσει ένα μοναδικό πεδίο για κάθε επανάληψη του βρόχου. Το αγαπημένο μου είναι να χρησιμοποιήσετε μια applyλειτουργία για να αντικαταστήσει το βρόχο for. Στη συνέχεια, η κάθε applyεπανάληψη τρέχει με τη δική του λειτουργία, ώστε οι τοπικές μεταβλητές είναι μοναδικά κάθε στοιχείο.

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))

Σημειώστε ότι θα αφαιρεθεί και το εξωτερικό observeEvent, δεδομένου ότι η λειτουργία του server τρέχει σε προετοιμασίας συνεδρία ούτως ή άλλως.

Απαντήθηκε 20/10/2018 στις 23:56
πηγή χρήστη

ψήφοι
0

Έχω βρεθεί μια λύση, αλλά υποθέτω ότι θα πρέπει να γίνει με πιο αποτελεσματικό τρόπο.

Μοιάζει με αυτό το πρόβλημα σχετίζεται με τεμπέληδες αξιολόγησης, έτσι ώστε μόνο το τελευταίο αντικείμενο που δημιουργείται έχει observeEvent εργασίας του. Έτσι, έχω αποφασίσει να δημιουργήσει, για κάθε επανάληψη του βρόχου νέες μεταβλητές χρησιμοποιώντας 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))

Όπως μπορεί να δει κανείς, κάθε βρόχος έχει νέες μεταβλητές, οπότε το πρόβλημα τεμπέλης-αξιολόγηση έχει λυθεί.

Αυτό που θέλω τώρα είναι αν αυτό μπορεί να γίνει με πιο αποτελεσματικό τρόπο.

Απαντήθηκε 20/10/2018 στις 15:02
πηγή χρήστη

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