Reputation: 728
I have an input variable input$shop_id
. Which is used to get data in server function using:
observeEvent(input$shop_id,{id<<-input$shop_id})
`Data=dbGetQuery(connection_name,paste0("SELECT * FROM tab_name WHERE id_shop=",id"))`
That Data is further used to create dynamic UI using selectInput()
output$dependant=renderUI({
selectInput("choice","Choose the Data you want to view",names(Data))
})
I can't come up with the logic of the arrangement of these functions. I cannot get it to work. I have created a sample data and similar sample code for someone to try on:
library(shiny)
library(ggplot2)
ui=fluidPage(
column(6,uiOutput("shop_select")),
column(6,uiOutput("cust_select")),
column(6,uiOutput("select3")),
column(12,offset=6,uiOutput("plot"))
)
server = function(input, output) {
#sample data
shopdata=data.frame(id=c(1,2,3,4,5,6,7,8,9,10),name=c("a","b","c","d","e","f","g","h","i","j"))
cdata=data.frame(id=c(123,465,6798,346,12341,45764,2358,67,457,5687,4562,23,12124,3453,12112),
name=c("sadf","porhg","wetgfjg","hwfhjh","yuigkug","syuif","rtyg","dygfjg","rturjh","kuser","zzsdfadf","jgjwer","jywe","jwehfhjh","kuwerg"),
shop=c(1,2,1,2,4,6,2,8,9,10,3,1,2,5,7),
bill_total=c(12341,123443,456433,234522,45645,23445,3456246,23522,22345,23345,23454,345734,23242,232456,345456),
crating=c(4,4.3,5,1.2,3.2,4,3.3,2.4,3.8,3,3.2,3.3,1.4,2.8,4.1))
output$shop_select=renderUI({
selectInput("shop_id","Shop ID",shopdata$id)
})
output$cust_select=renderUI({
selectInput("cust_id","Customer ID",cdata$id,multiple = T)
})
output$select3=renderUI({
a=input$shop_id
selectInput("choice","Choose the Data you want to view",names(cdata))
})
output$plot=renderUI({
renderPlot({
require(input$choice)
plotOutput(
ggplot(cdata,aes(x=cust_id,y=input$choice))
)})})
}
shinyApp(ui=ui,server=server)
I know I am not clear on the question. Fixing the code which I posted is more than enough to clear my doubt. Basically, I just need to know what is the logic when we have to use while using a renderUI()
which is dependent on another renderUI()
Upvotes: 1
Views: 90
Reputation: 10671
If you want to set up a series of subsetting operations and then call renderUI()
s on each subset, you will need to take advantage of Shiny's reactive({})
expressions.
Reactive expressions are code chunks that produce variables and their magic is that they "watch" for any changes to their input data. So in your case one you select a shop_id
in the first UI element, the reactive expression detects that and updates itself, automatically!
Here is an example showing the updating, just select different shop_id's and watch the available cust_id
s change on the fly.
library(shiny)
library(ggplot2)
library(tidyverse)
ui=fluidPage(
column(6,uiOutput("shop_select")),
column(6,uiOutput("cust_select")),
column(6,uiOutput("select3")),
column(12,offset=6,tableOutput("plot"))
)
server = function(input, output) {
#sample data
shopdata=data.frame(id=c(1,2,3,4,5,6,7,8,9,10),name=c("a","b","c","d","e","f","g","h","i","j"))
cdata=data.frame(id=c(123,465,6798,346,12341,45764,2358,67,457,5687,4562,23,12124,3453,12112),
name=c("sadf","porhg","wetgfjg","hwfhjh","yuigkug","syuif","rtyg","dygfjg","rturjh","kuser","zzsdfadf","jgjwer","jywe","jwehfhjh","kuwerg"),
shop=c(1,2,1,2,4,6,2,8,9,10,3,1,2,5,7),
bill_total=c(12341,123443,456433,234522,45645,23445,3456246,23522,22345,23345,23454,345734,23242,232456,345456),
crating=c(4,4.3,5,1.2,3.2,4,3.3,2.4,3.8,3,3.2,3.3,1.4,2.8,4.1))
output$shop_select=renderUI({
selectInput("shop_id","Shop ID",shopdata$id)
})
cdata_reactive <- reactive({
req(input$shop_id)
filter(cdata, shop == input$shop_id)
})
output$cust_select=renderUI({
selectInput("cust_id","Customer ID",cdata_reactive()$id, multiple = T)
})
output$select3=renderUI({
selectInput("choice","Choose the Data you want to view",names(cdata_reactive()))
})
output$plot <- renderTable({
filter(cdata_reactive(), id %in% input$cust_id) %>%
.[input$choice]
})
}
shinyApp(ui=ui,server=server)
Upvotes: 1
Reputation: 12155
renderUI
generates UI
elements. Therefore it can only contain ui
functions. You need to use it to generate the plotOutput
and then use renderPlot
separately to add content.aes
call are the names of variables in the data frame you provided. Therefore x
should be id
not the values of input$cust_id
(which must be called as input$cust_id
, since it refers to an input object.input$choice
returns a string, not an object, so you can't use it normally in aes
(recall that if this was a normal dataframe your aes would be aes(x=id, y=choice)
not aes(x='id', y='choice')
. Therefore, you need to use aes_
with the as.name
function to convert those strings into proper variable names.input$cust_id
is filter cdata
to only include rows with the chosen id
values. dplyr::filter
is the best way to do that.geom_*
in your ggplot call which is needed to actually render your data.If you replace your output$plot <- ...
call with the below code it should work the way I think you want it to:
output$plot=renderUI({
plotOutput('plotout')
})
output$plotout <- renderPlot({
ggplot(dplyr::filter(cdata, id %in% input$cust_id),
aes_(x=as.name('id'),y=as.name(input$choice))) +
geom_point()
})
As for the question in your title, you only need to use observeEvent
if you want to limit the code in the expression to only run when a specific trigger occurs. Any reactive expression (reactive
, observe
, render_
etc.) will become invalidated and update itself if any reactive value (either a reactiveValues
object or an input$...
) changes. If you have an input$
or a reactive value in a render_
block, it will update if they change -- no observeEvent
needed.
Upvotes: 1