Credo che questo post ha ancora qualche rilevanza. Quindi ecco la mia soluzione su come aggiungere quasi ogni output di interfaccia possibile ai popup di opuscoli.
possiamo raggiungere questo fare le seguenti operazioni:
Inserire l'elemento dell'interfaccia utente popup come carattere all'interno del campo pop-up standard di foglio. Come personaggio significa, non è il shiny.tag
, ma semplicemente un normale div
. Per esempio. il classico uiOutput("myID")
diventa <div id="myID" class="shiny-html-output"><div>
.
I popup vengono inseriti in uno speciale div
, nel pannello di selezione foglio . Aggiungiamo un EventListener per monitorare se il suo contenuto cambia. (Nota: Se il popup scompare, che si intendono tutti i bambini di questa div
vengono rimossi, quindi questo non è un problema di visibilità, ma di esistenza.)
Quando un bambino è allegato, vale a dire un popup è apparendo, noi leghiamo tutti gli input/output lucidi all'interno del popup. Quindi, il senza vita uiOutput
è pieno di contenuti come dovrebbe essere. (Uno avrei sperato che lucida lo fa automaticamente, ma non riesce a registrare questa uscita, dal momento che è compilato dal Volantini backend.)
Quando il pop-up è cancellato, Brillante, inoltre, non unbind esso. Questo è problematico, se si apre nuovamente il popup e si genera un'eccezione (ID duplicato). Una volta eliminato dal documento, non può più essere non associato.Quindi fondamentalmente lo clona l'elemento eliminato a uno smaltimento- div
dove può essere non associato correttamente e quindi cancellarlo definitivamente.
Ho creato un'applicazione di esempio che (credo) mostra tutte le potenzialità di questa soluzione e spero che è stato progettato abbastanza facile, che chiunque può adattarlo. La maggior parte di questa app è per show, quindi ti prego di perdonare che ha parti irrilevanti.
library(leaflet)
library(shiny)
runApp(
shinyApp(
ui = shinyUI(
fluidPage(
# Copy this part here for the Script and disposal-div
uiOutput("script"),
tags$div(id = "garbage"),
# End of copy.
leafletOutput("map"),
verbatimTextOutput("Showcase")
)
),
server = function(input, output, session){
# Just for Show
text <- NULL
makeReactiveBinding("text")
output$Showcase <- renderText({text})
output$popup1 <- renderUI({
actionButton("Go1", "Go1")
})
observeEvent(input$Go1, {
text <<- paste0(text, "\n", "Button 1 is fully reactive.")
})
output$popup2 <- renderUI({
actionButton("Go2", "Go2")
})
observeEvent(input$Go2, {
text <<- paste0(text, "\n", "Button 2 is fully reactive.")
})
output$popup3 <- renderUI({
actionButton("Go3", "Go3")
})
observeEvent(input$Go3, {
text <<- paste0(text, "\n", "Button 3 is fully reactive.")
})
# End: Just for show
# Copy this part.
output$script <- renderUI({
tags$script(HTML('
var target = document.querySelector(".leaflet-popup-pane");
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if(mutation.addedNodes.length > 0){
Shiny.bindAll(".leaflet-popup-content");
};
if(mutation.removedNodes.length > 0){
var popupNode = mutation.removedNodes[0].childNodes[1].childNodes[0].childNodes[0];
var garbageCan = document.getElementById("garbage");
garbageCan.appendChild(popupNode);
Shiny.unbindAll("#garbage");
garbageCan.innerHTML = "";
};
});
});
var config = {childList: true};
observer.observe(target, config);
'))
})
# End Copy
# Function is just to lighten code. But here you can see how to insert the popup.
popupMaker <- function(id){
as.character(uiOutput(id))
}
output$map <- renderLeaflet({
leaflet() %>%
addTiles() %>%
addMarkers(lat = c(10, 20, 30), lng = c(10, 20, 30), popup = lapply(paste0("popup", 1:3), popupMaker))
})
}
), launch.browser = TRUE
)
Nota: Ci si potrebbe chiedere, perché lo script viene aggiunto dal lato server. Ho riscontrato che, in caso contrario, l'aggiunta di EventListener non riesce, perché la mappa Leaflet non è ancora stata inizializzata. Scommetto che con qualche conoscenza di jQuery non c'è bisogno di fare questo trucco.
Risolvere questo è stato un lavoro duro, ma penso che ne valesse la pena, ora che le mappe Leaflet hanno qualche utilità in più. Divertiti con questa soluzione e chiedi se ci sono domande a riguardo!
Il fattore limitante qui è che 'popup' prende solo qualcosa che si riduce a una stringa. Ciò significa che puoi usare qualunque HTML tu voglia e anche JavaScript inline, ma non R, che è una specie di punto. Se lavori con il volantino nel suo JavaScript nativo potresti probabilmente andare oltre, ma a un certo punto diventa assurdo. Un modo molto più semplice di presentare le stesse informazioni è di rendere reattivo un pannello separato sul pennarello cliccato, in modo da poter codificare le informazioni specifiche dei marker in R. Forse rubare [questa formattazione] (http://shiny.rstudio.com/ galleria/SuperZip-example.html). – alistaire
Non so se questo è ancora aperto, ma puoi fornire un esempio riproducibile con la tua app lucida. – MLavoie
Ciao @MLavoie, il codice per la riproducibilità è disponibile sul mio account github (vedi il post iniziale, ci sono 2 link: github e shinyapps.io). Cordiali saluti – cho7tom