我有一个闪亮的应用程序,向用户显示信息。每行代表一个地点,因此您可以使用两个selectInputs
来过滤使用特定城市名称和区域的数据。我正在使用reactive()
来过滤数据。结果数据显示在下面,信息框和地图显示每个地方的位置。
信息框有一个操作按钮,一旦点击,只显示与该框对应的标记。我正在使用leafletProxy
更新我的地图。
另外,在我的地图中,我的制作人员弹出窗口包含一个动作按钮,因此我想点击该按钮,只显示与地图上的地点对应的信息框,而不显示其他信息框。当用户点击地图上的按钮时,我以为我可以再次过滤数据eventReactive
,但我似乎无法做到这一点。按钮ID由lapply
以动态方式生成,因此我不知道如何在observeEvent
或eventReactive
中声明该按钮。有什么建议?
下面的代码示例:
name<-sample(c('a','b','c'),replace=T,5)
area1<-sample(c(0,1),replace=T,5)
area2<-sample(c(0,1),replace=T,5)
area3<-sample(c(0,1),replace=T,5)
LAT<-runif(5,min=-26, max=-22)
LONG<-runif(5,min=-54, max=-48)
data<-data.frame(name,area1,area2,area3,LAT,LONG)
ui <- shinyUI(fluidPage(
selectInput('muni',label='Select city',
choices=c('Show all',sort(levels(data$name)),selected=NULL)),
selectInput('area',label='Select area',
choices=c('Show all','area1','area2','area3',selected=NULL)),
HTML('<table border="0"><tr><td style="padding: 8px">
<a id="reset" href="#" style="text-indent: 0px;"
class="action-button shiny-bound-input">
Reset</a></td></tr></table>'),
htmlOutput('box'),
leafletOutput('map')
))
server <- function (input, output, session) {
data1<-reactive({
if (input$muni!='Show all') {
data<-data[which(data$name==input$muni),]
}
if (input$area!='Show all') {
data<-data[data[input$area]!=0,]
}
return(data)
})
observeEvent(input$reset, {
updateSelectInput(session,'muni',selected='Show all')
updateSelectInput(session,'area',selected='Show all')
})
output$box <- renderUI({
data<-data1()
num<-as.integer(nrow(data))
func_areas <- function(areas) sub(",\\s+([^,]+)$", " and \\1",
toString(areas))
lapply(1:num, function(i) {
bt <- paste0('go_btn',i)
fluidRow(
HTML(paste0('<div style="border: 1px solid #00000026;
border-radius: 10px; padding: 10px;">
<span style="font-size:14px font-weight:bold;">',
data$name[i],' - areas: ',
func_areas(colnames(data[i,names(data)[2:4]])
[which(data[i,names(data)[2:4]]!=0)]),'</span></br>',
actionButton(bt,'See map',icon=icon('map-marker',lib='font-awesome')),
HTML('</div></br>')
)))
})
})
output$map<-renderLeaflet({
data<-data1()
rownames(data)<-seq(1:nrow(data))
pop<-paste0('<strong>',data$name,'</strong></br>',
'<a id="info',rownames(data),'" href="#" style="text-indent: 0px;"
class="action-button shiny-bound-input"
onclick="{Shiny.onInputChange(\'info',rownames(data),'\',
(Math.random() * 1000) + 1);}">
<i class="fa fa-info-circle"></i>Show info</a>')
leaflet(data) %>%
addProviderTiles("Esri.WorldTopoMap") %>%
setView(-51.5,-24.8,zoom=7) %>%
addMarkers(lng=~data$LONG,lat=~data$LAT,popup=pop)
})
lapply(1:nrow(data), function(i) {
bt <- paste0('go_btn',i)
observeEvent(input[[bt]], {
data<-data1()
rownames(data)<-seq(1:nrow(data))
pop<-paste0('<strong>',data$name[i],'</strong></br>',
'<a id="info',rownames(data),'" href="#" style="text-indent: 0px;"
class="action-button shiny-bound-input"
onclick="{Shiny.onInputChange(\'info',rownames(data),'\',
(Math.random() * 1000) + 1);}">
<i class="fa fa-info-circle"></i>Show info</a>')
leafletProxy('map',data=data,session=session) %>%
clearMarkers() %>%
setView(data$LONG[i],data$LAT[i],zoom=15) %>%
addMarkers(lng=data$LONG[i],lat=data$LAT[i],popup=pop)
})
})
}
shinyApp(ui, server)
感谢您的帮助,对不起,如果我写错了,第一次使用stackoverflow。
答案 0 :(得分:0)
好吧,我并不是100%确定这是理想的行为,但我认为这足以让你有所作为,所以你可以达到你想要的效果。
我为您创建的div添加了一个ID,然后使用lapply
为每个按钮创建一个单独的observeEvent
。然后,observeEvent会从相应div上的show
包中触发hide
或shinyjs
。
我在添加或修改的行之上添加了#added by Florian
或modified by Florian
,因为代码很长。我希望这有帮助!如果出现任何其他问题,请告诉我。
# Added by Florian
library(shinyjs)
name<-sample(c('a','b','c'),replace=T,5)
area1<-sample(c(0,1),replace=T,5)
area2<-sample(c(0,1),replace=T,5)
area3<-sample(c(0,1),replace=T,5)
LAT<-runif(5,min=-26, max=-22)
LONG<-runif(5,min=-54, max=-48)
data<-data.frame(name,area1,area2,area3,LAT,LONG)
ui <- shinyUI(fluidPage(
# Added by Florian
useShinyjs(),
selectInput('muni',label='Select city',
choices=c('Show all',sort(levels(data$name)),selected=NULL)),
selectInput('area',label='Select area',
choices=c('Show all','area1','area2','area3',selected=NULL)),
HTML('<table border="0"><tr><td style="padding: 8px">
<a id="reset" href="#" style="text-indent: 0px;"
class="action-button shiny-bound-input">
Reset</a></td></tr></table>'),
htmlOutput('box'),
leafletOutput('map')
))
server <- function (input, output, session) {
data1<-reactive({
if (input$muni!='Show all') {
data<-data[which(data$name==input$muni),]
}
if (input$area!='Show all') {
data<-data[data[input$area]!=0,]
}
return(data)
})
observeEvent(input$reset, {
updateSelectInput(session,'muni',selected='Show all')
updateSelectInput(session,'area',selected='Show all')
# Added by Florian
for (i in 1:as.integer(nrow(data)))
{
shinyjs::show(paste0('mydiv_',i))
}
})
output$box <- renderUI({
data<-data1()
num<-as.integer(nrow(data))
func_areas <- function(areas) sub(",\\s+([^,]+)$", " and \\1",
toString(areas))
#modified by Florian: added div id
lapply(1:num, function(i) {
bt <- paste0('go_btn',i)
fluidRow(
HTML(paste0('<div id="mydiv_',i,'"; style="border: 1px solid #00000026;
border-radius: 10px; padding: 10px;">
<span style="font-size:14px font-weight:bold;">',
data$name[i],' - areas: ',
func_areas(colnames(data[i,names(data)[2:4]])
[which(data[i,names(data)[2:4]]!=0)]),'</span></br>',
actionButton(bt,'See map',icon=icon('map-marker',lib='font-awesome')),
HTML('</div></br>')
)))
})
})
# Added by Florian
lapply(1:as.integer(nrow(data)),function(x)
{
observeEvent(input[[paste0('go_btn',x)]], {
logjs('Click!')
shinyjs::show(paste0('mydiv_',x))
for (i in 1:as.integer(nrow(data)))
{
if(i!=x)
{
shinyjs::hide(paste0('mydiv_',i))
}
}
} )
})
output$map<-renderLeaflet({
data<-data1()
pop<-paste0('<strong>',data$name,'</strong></br>',
'<a id="info" href="#" style="text-indent: 0px;"
class="action-button shiny-bound-input"
onclick="{Shiny.onInputChange(\'info\', (Math.random() * 1000) + 1);}">
<i class="fa fa-info-circle"></i>Show info</a>')
leaflet(data) %>%
addProviderTiles("Esri.WorldTopoMap") %>%
setView(-51.5,-24.8,zoom=7) %>%
addMarkers(lng=~data$LONG,lat=~data$LAT,popup=pop)
})
lapply(1:nrow(data), function(i) {
bt <- paste0('go_btn',i)
observeEvent(input[[bt]], {
data<-data1()
pop<-paste0('<strong>',data$name[i],'</strong></br>',
'<a id="info" href="#" style="text-indent: 0px;"
class="action-button shiny-bound-input"
onclick="{Shiny.onInputChange(\'info\', (Math.random() * 1000) + 1);}">
<i class="fa fa-info-circle"></i>Show info</a>')
leafletProxy('map',data=data,session=session) %>%
clearMarkers() %>%
setView(data$LONG[i],data$LAT[i],zoom=15) %>%
addMarkers(lng=data$LONG[i],lat=data$LAT[i],popup=pop)
})
})
}
shinyApp(ui, server)