I need help with the below shiny app server function. My problem is values$npv always comes out null, not even with a 0. and I think the fun function is not doing the right thing and i'm out of ideas.
If I hard-code the renderText with paste("Net Present Value:", isolate(input$val_inv)) i always have a result but not what i want and this makes me guess the fun function is not working as it should.
inline_numericInput=function(ni){
tags$div( class="form-inline",ni)
}
ui <- shinyUI(fluidPage(
tags$head(tags$style("#side_panel{
padding-left:10px;
}
.form-group {
margin-bottom: 15px !important;
}
.form-inline .form-control {
width:80%;
}
label{ width:30px;}
")),
titlePanel("Example"),
sidebarLayout(
sidebarPanel(width = 4,id="side_panel",
fluidRow(
column(6, inline_numericInput(numericInput("val_inv", label = "Inv:", value = 0))),
),
fluidRow(
column(6, inline_numericInput(numericInput("val_r", label = "R:", value = 0))),
),
fluidRow(
column(6, inline_numericInput(numericInput("val_n", label = "N:", min = 50,value = 50))),
column(6, inline_numericInput(actionButton("btn_calcnpv", label = "Compute NPV")))
)
),
mainPanel(
p('Results:'),
textOutput("val_npv")
)
)
))
server <- function(input, output) {
values <- reactiveValues()
values$npv <- 0
observe({
input$btn_calcnpv
fun <- function(n){
cf <- 0
for (i in 1:n){
cf <- cf + isolate(input$val_inv)/(1+input$var_r)**i
}
cf
}
values$npv <- fun(isolate(input$val_n))- isolate(input$val_inv)
#values$npv <- values$npv - isolate(input$val_inv)
})
output$val_npv <- renderText({
if(input$btn_calcnpv)
paste("Net Present Value:", values$npv)
else ""
})
}
shinyApp(ui, server)
Here is an answer using eventReactive and not so many isolations.
Furthermore, the inputs are coerced to numbers before the calculation takes place.
Using eventReactive, the calculation is started by pressing the compute-button.
server <- function(input, output) {
npv <- eventReactive(input$btn_calcnpv, {
val_inv <- as.numeric(input$val_inv)
val_r <- as.numeric(input$val_r)
val_n <- as.numeric(input$val_n)
fun <- function(n){
cf <- 0
for (i in 1:n){
cf <- cf + val_inv/(1+val_r)**i
}
cf
}
temp <- fun(val_n)- val_inv
temp
})
output$val_npv <- renderText({
req(npv())
paste("Net Present Value:", npv())
})
}
Related
I am working in a shiny app to compare multiple items according to an input defined by the user. The code works fine but I have an issue. I do not know what function I should apply in order to display the results of some computing as tables in the right side of the app. The code of the app is next:
library(shiny)
library(shinydashboard)
#Function
compute <- function(firstitem,seconditem)
{
Sum <- firstitem+seconditem
Difference <- firstitem+seconditem
Product <- firstitem*seconditem
Ratio <- firstitem/seconditem
Res <- data.frame(C1=Sum,C2=Difference,C3=Product,C4=Ratio)
return(Res)
}
#App
ui = shinyUI(fluidPage(
titlePanel("Compare"),
sidebarLayout(
sidebarPanel(
numericInput("numitems", label = "Number of items to compare?",
min = 1, max = 5, value = 1),
uiOutput("period_cutpoints"),
uiOutput("period_cutpoints2"),
actionButton("submit", "Submit")
),
mainPanel(
textOutput("numitems"),
textOutput("cutpoints")
)
)
))
server = shinyServer(function(input, output, session) {
output$period_cutpoints<-renderUI({
req(input$numitems)
lapply(1:(input$numitems), function(i) {
numericInput(inputId=paste0("firstitem",i),
label=paste0("Enter the value of first item ", i, ":"),value = 0)
})
})
output$period_cutpoints2<-renderUI({
req(input$numitems)
lapply(1:(input$numitems), function(i) {
numericInput(inputId=paste0("seconditem",i),
label=paste0("Enter the value of second item ", i, ":"),value = 0)
})
})
seldates <- reactiveValues(x=NULL)
observeEvent(input$submit, {
seldates$x <- list()
lapply(1:(input$numitems), function(i) {
seldates$x[[i]] <- compute(firstitem = input[[paste0("firstitem", i)]],seconditem = input[[paste0("seconditem", i)]])
})
})
output$cutpoints <- renderText({as.character(seldates$x)})
})
shinyApp(ui = ui, server = server)
It is working but my issue is that I do not know how to set the content of seldates, which are dataframes, as tables that should appear one after another. This task is done with output$cutpoints but I can not get them as Tables:
Does anybody know how can I fix this issue? Many thanks!
Try this
library(shiny)
library(shinydashboard)
library(DT)
#Function
compute <- function(firstitem,seconditem)
{
Sum <- firstitem+seconditem
Difference <- firstitem+seconditem
Product <- firstitem*seconditem
Ratio <- firstitem/seconditem
Res <- data.frame(C1=Sum,C2=Difference,C3=Product,C4=Ratio)
return(Res)
}
#App
ui = shinyUI(fluidPage(
titlePanel("Compare"),
sidebarLayout(
sidebarPanel(
numericInput("numitems", label = "Number of items to compare?",
min = 1, max = 5, value = 1),
uiOutput("period_cutpoints"),
uiOutput("period_cutpoints2"),
actionButton("submit", "Submit")
),
mainPanel(
textOutput("numitems"),
textOutput("cutpoints"),
uiOutput("t1")
)
)
))
server = shinyServer(function(input, output, session) {
output$period_cutpoints<-renderUI({
req(input$numitems)
lapply(1:(input$numitems), function(i) {
numericInput(inputId=paste0("firstitem",i),
label=paste0("Enter the value of first item ", i, ":"),value = i)
})
})
output$period_cutpoints2<-renderUI({
req(input$numitems)
lapply(1:(input$numitems), function(i) {
numericInput(inputId=paste0("seconditem",i),
label=paste0("Enter the value of second item ", i, ":"),value = i+i)
})
})
seldates <- reactiveValues(x=NULL)
observeEvent(input$submit, {
seldates$x <- list()
lapply(1:(input$numitems), function(i) {
seldates$x[[i]] <- compute(firstitem = input[[paste0("firstitem", i)]],seconditem = input[[paste0("seconditem", i)]])
})
})
output$cutpoints <- renderText({as.character(seldates$x)})
observeEvent(input$submit, {
lapply(1:(input$numitems), function(i) {
output[[paste0("table",i)]] <- renderDT(seldates$x[[i]])
})
output$t1 <- renderUI({
tagList(
lapply(1:(input$numitems), function(i) {
DTOutput(paste0("table",i))
})
)
})
})
})
shinyApp(ui = ui , server = server)
I have 2 checkboxes and 1 action button. When clicking on either of the checkboxes, a graph should output BUT only after clicking on the action button. The code I have bellow does this well already. My issue here is that once the action button has been clicked and the graph generated, unclicking the checkbox removes the graph. Similarly, clicking again generates a new graph without clicking on the action button. I would like for the graph to stay on the screen for as long as I dont click on the action button again. I imagine this has to do with "isolating" the checkboxes but Im not too sure how to do so.
As a side note, imagine there was a third function generating a plot in my server when clicking on the action button (regardless of the checkboxes). Is there a way to code my "showmodal, removemodal" such that the pop up stays while all functions are running (instead of only during the first function)?
Here is my code
library(shiny)
#Function 1
X <- function(a,b,c){
plot(c(a,b),c(b,c))
}
#Function 2
Y <- function(d,e,f){
plot(c(d,e),c(e,f))
}
ui <- fluidPage(
titlePanel("title"),
sidebarLayout(
sidebarPanel(
checkboxInput("EF", "Efficient Frontier"),
checkboxInput("MonteCarlo", "Monte Carlo Simulation"),
actionButton("Go", "Go", style="color: #fff; background-color: #337ab7; border-color: #2e6da4; margin: auto")
),
mainPanel(
fluidRow(
align = "center",
conditionalPanel(condition = "input.EF == true", plotOutput("GraphEF")),
conditionalPanel(condition = "input.MonteCarlo == true", plotOutput("GraphMC"))
)
)
)
)
server <- function(input, output) {
OPw <- reactiveValues()
output$Graphw <- renderPlot({
OPw$PC}, height = 400, width = 400)
observeEvent(input$Go, {
showModal(modalDialog("Loading... Please Wait", footer=NULL))
output$GraphEF <- renderPlot({ #Efficient Frontier
if(input$EF){
X(5,10,15)
}
}, height = 550, width = 700)
output$GraphMC <- renderPlot({ #Monte Carlo Simulation
if(input$MonteCarlo){
Y(5,10,15)
}
},height = 550, width = 700)
removeModal() #Removes Loading Pop-up Message
})
}
shinyApp(ui = ui, server = server)
Thanks a lot for your help!
Perhaps you should use eventReactive(). Try this
library(shiny)
# Function 1
X <- function(a, b, c) {
plot(c(a, b), c(b, c))
}
# Function 2
Y <- function(d, e, f) {
plot(c(d, e), c(e, f))
}
ui <- fluidPage(
titlePanel("title"),
sidebarLayout(
sidebarPanel(
checkboxInput("EF", "Efficient Frontier"),
checkboxInput("MonteCarlo", "Monte Carlo Simulation"),
actionButton("Go", "Go", style = "color: #fff; background-color: #337ab7; border-color: #2e6da4; margin: auto")
),
mainPanel(
fluidRow(
align = "center",
uiOutput("plot1"),
plotOutput("GraphMC")
)
)
)
)
server <- function(input, output) {
GEF <- eventReactive(input$Go, {
if (input$EF) {
X(5, 10, 15)
} else {
NULL
}
})
showme <- eventReactive(input$Go, {
if (input$EF) TRUE else FALSE
})
GMC <- eventReactive(input$Go, {
if (isolate(input$MonteCarlo)) {
Y(5, 10, 15)
} else {
NULL
}
})
output$GraphMC <- renderPlot({
GMC()
})
output$GraphEF <- renderPlot({ # Efficient Frontier
GEF()
})
output$plot1 <- renderUI({
if (showme()) {plotOutput("GraphEF")} else NULL
})
observeEvent(input$Go, {
showModal(modalDialog("Loading... Please Wait", footer = NULL))
Sys.sleep(2)
removeModal() # Removes Loading Pop-up Message
})
}
shinyApp(ui = ui, server = server)
Leaving a conditionalPanel-approach, which is referring to a discussion over here:
library(shiny)
# Function 1
X <- function(a, b, c) {
plot(c(a, b), c(b, c))
}
# Function 2
Y <- function(d, e, f) {
plot(c(d, e), c(e, f))
}
ui <- fluidPage(
titlePanel("title"),
sidebarLayout(
sidebarPanel(
checkboxInput("EF", "Efficient Frontier"),
checkboxInput("MonteCarlo", "Monte Carlo Simulation"),
actionButton("Go", "Go", style = "color: #fff; background-color: #337ab7; border-color: #2e6da4; margin: auto")
),
mainPanel(
fluidRow(
align = "center",
conditionalPanel("output.showme == true", plotOutput("GraphEF")),
plotOutput("GraphMC")
)
)
)
)
server <- function(input, output) {
GEF <- eventReactive(input$Go, {
if (input$EF) {
X(5, 10, 15)
} else {
NULL
}
})
output$showme <- eventReactive(input$Go, {
if (input$EF) TRUE else FALSE
})
outputOptions(output, "showme", suspendWhenHidden = FALSE)
GMC <- eventReactive(input$Go, {
if (isolate(input$MonteCarlo)) {
Y(5, 10, 15)
} else {
NULL
}
})
output$GraphMC <- renderPlot({
GMC()
})
output$GraphEF <- renderPlot({ # Efficient Frontier
GEF()
})
observeEvent(input$Go, {
showModal(modalDialog("Loading... Please Wait", footer = NULL))
Sys.sleep(2)
removeModal() # Removes Loading Pop-up Message
})
}
shinyApp(ui = ui, server = server)
Furthermore, please see this related answer.
The modal is working well, because both functions take so little time to run it creates de sensation than is there less than it should be. We can show this by adding a sys.sleep to simulate a long calculation.
Regarding the checkboxes, using conditionalPanel will hide or show the plots independently of the presence of isolate inside the server. A workaround is just to return NULL when the checkbox is not clicked.
library(shiny)
# Function 1
X <- function(a, b, c) {
plot(c(a, b), c(b, c))
}
# Function 2
Y <- function(d, e, f) {
plot(c(d, e), c(e, f))
}
ui <- fluidPage(
titlePanel("title"),
sidebarLayout(
sidebarPanel(
checkboxInput("EF", "Efficient Frontier"),
checkboxInput("MonteCarlo", "Monte Carlo Simulation"),
actionButton("Go", "Go", style = "color: #fff; background-color: #337ab7; border-color: #2e6da4; margin: auto")
),
mainPanel(
fluidRow(
align = "center",
plotOutput("GraphEF"),
plotOutput("GraphMC")
)
)
)
)
server <- function(input, output) {
OPw <- reactiveValues()
output$Graphw <- renderPlot(
{
OPw$PC
},
height = 400,
width = 400
)
observeEvent(input$Go, {
showModal(modalDialog("Loading... Please Wait", footer = NULL))
output$GraphEF <- renderPlot(
{ # Efficient Frontier
if (isolate(input$EF)) {
X(5, 10, 15)
} else {
NULL
}
},
height = 550,
width = 700
)
Sys.sleep(2)
output$GraphMC <- renderPlot(
{ # Monte Carlo Simulation
if (isolate(input$MonteCarlo)) {
Y(5, 10, 15)
} else {
NULL
}
},
height = 550,
width = 700
)
removeModal() # Removes Loading Pop-up Message
})
}
shinyApp(ui = ui, server = server)
In the below MWE code, the object input2 is optionally called by the user by clicking the "Show" radio button for Input 2. Default setting is to hide input2. However, when first invoking the App, input2 quickly flashes by before being hidden by the observeEvent.
This flashing is much more pronounced in the non-MWE version of the code.
There is a related post In R shiny, how to eliminate flashing of all conditional panels in sidebar when first invoking the App without using renderUI? that addresses this issue for conditionalPanel. But here there is no conditionalPanel.
I do not want to use renderUI to resolve this issue!! As renderUI has drawbacks I don't want to re-introduce.
MWE code:
library(shiny)
library(shinyjs)
f <- function(action,i){as.character(checkboxInput(paste0(action,i),label=NULL))}
actions <- c("show", "reset")
tbl <- t(outer(actions, c(1,2), FUN = Vectorize(f)))
colnames(tbl) <- c("Show", "Reset")
rownames(tbl) <- c("Input 2", "Input 3")
ui <- fluidPage(
useShinyjs(),
tags$head(
tags$style(HTML(
"td .checkbox {margin-top: 0; margin-bottom: 0;}
td .form-group {margin-bottom: 0;}"
))
),
br(),
sidebarLayout(
sidebarPanel(
numericInput("input1", "Input 1:", 10, min = 1, max = 100),
h5(strong("Add inputs:")),
tableOutput("checkboxes"),
numericInput("input2", "Input 2:", 10, min = 1, max = 100),
),
mainPanel()
)
)
server <- function(input, output, session){
output[["checkboxes"]] <-
renderTable({tbl},
rownames = TRUE, align = "c",
sanitize.text.function = function(x) x
)
observeEvent(input[["show1"]], {
if(input[["show1"]] %% 2 == 1){shinyjs::show(id = "input2")} else
{shinyjs::hide(id = "input2")}
})
}
shinyApp(ui, server)
It takes some time in the event loop until observerEvent is called the first time.
By default, it will be displayed at the very beginning.
This results into a flash.
Just hide input2 at the very beginning of the server function:
server <- function(input, output, session) {
# Avoid flashing
shinyjs::hide(id = "input2")
output[["checkboxes"]] <-
renderTable(
{
tbl
},
rownames = TRUE,
align = "c",
sanitize.text.function = function(x) x
)
observeEvent(input[["show1"]], {
if (input[["show1"]] %% 2 == 1) {
shinyjs::show(id = "input2")
} else {
shinyjs::hide(id = "input2")
}
})
}
You can also use hidden
hidden(numericInput("input2", "Input 2:", 10, min = 1, max = 100))
and toggle:
observeEvent(input[["show1"]], {
toggle("input2")
},ignoreNULL = FALSE)
I am developing the Shiny app and I am unable to sum the values entered in dynamically created textInput.
The RCode used is as follows:
ui <- fluidPage(
fluidRow(
column(3, offset = 3,wellPanel(textOutput("text2"))),
column(3,wellPanel(textOutput("text3"))),
column(3,wellPanel(textOutput("text4")))
)
)
server <- function(input, output, session){
observeEvent(input$view, {
output$inputGroup = renderUI({
#code for generating textBoxes and corresponding Id's dynamically
input_list <- lapply(1:(nrow(df())*3), function(i) {
inputName <- paste("id", i, sep = "")
textInputRow<-function (inputId,value)
{
textAreaInput(inputName,"", width = "200px", height = "43px", resize = "horizontal")
}
column(4,
textInputRow(inputName, "")
)
})
do.call(tagList, input_list)
})
})
#code for adding the values and displaying the sum
output$text2 <- renderText({
tot = nrow(df())*3
sum1 = 0
for(lim in 1:tot){
if(lim %% 3 == 1){
inp = paste("id",lim)
sum1 = sum1 + input[[inp]]
}
}
})
}
shinyApp(ui = ui, server = server)
The output is :
Can anyone help me with this code?
While your question is modified, Here's a reproducible code for summing values entered in the textbox:
## Only run examples in interactive R sessions
if (interactive()) {
ui <- fluidPage(
textInput("input1", "Input1", 1),
textInput("input2", "Input2", 2),
tags$h3('Result:'),
verbatimTextOutput("value")
)
server <- function(input, output) {
output$value <- renderText({ as.numeric(input$input1) + as.numeric(input$input2)})
}
shinyApp(ui, server)
}
I am trying to dynamically render multiple text output from multiple text input. I tried to use this very helpfull example and this one too.
This conversation is also helpfull.
But when I try to adapt this examples on the following script, I have a problem of output update. Apparently, only the last element was read and updated. It's probably a reactivity problem but it seems to be difficult to associate reactive{()} and renderUI{()}functions.
rm(list = ls())
library(shiny)
creatDataElem <- function(ne, input) {
x1 <- lapply(1:ne, function(i) {
textInput(paste0("elemName", i),
label = h4(strong("Name of dataset element")),
value = "")
})
return(x1)
}
ui = (fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("elemNb",
"Number of elements", value = 1, min = 1,
max = 3)
,
conditionalPanel(
condition = "input.elemNb == 1",
creatDataElem(1)
),
conditionalPanel(
condition = "input.elemNb == 2",
creatDataElem(2)
),
conditionalPanel(
condition = "input.elemNb == 3",
creatDataElem(3)
)
),
mainPanel(
uiOutput("nameElem")
)
)
)
)
server = function(input, output, session) {
max_elem <- 3
# Name
output$nameElem <-renderUI({
nameElem_output_list <- lapply(1:input$elemNb, function(i) {
elemName <- paste0("elemName", i)
tags$div(class = "group-output",
verbatimTextOutput(elemName)
)
})
do.call(tagList, nameElem_output_list)
})
for (i in 1:max_elem) {
local({
force(i)
my_i <- i
elemName <- paste0("elemName", my_i)
output[[elemName]] <- renderPrint(input[[elemName]])
})
}
}
runApp(list(ui = ui, server = server))
The idea with a reactive({}) function is to add an independant object (a function in this case) like:
nameElem <- reactive({
if (input$goElem == 0) {
return()
} else {
isolate({
if (is.null(input$elemName)) {
return()
} else if (test(input$elemName)) {
return("TEST RESULT")
} else {
return(input$elemName)
}
})
}
})
and to use renderUI on this object (with an ActionButton).
So, if someone knows why the output does not return the good object...
I think one of your problems is that your creatDataElem function is such that when it is called with argument ne=3, the first and second textInput elements are created again (and their value "lost").
Anyway, I think one solution would be to create those textInput elements as an "uiOutput".
You'll find a possible solution below which (I think) does what you want.
Lise
rm(list = ls())
library(shiny)
ui = (fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("elemNb",
"Number of elements", value = 1, min = 1,
max = 3),
uiOutput("myUI")
),
mainPanel(
uiOutput("nameElem")
)
)
)
)
server = function(input, output, session) {
output$myUI=renderUI({
w=""
for (i in 1:input$elemNb){
w=paste0(w,
textInput(paste0("elemName",i),label='Name of dataset element'))
}
HTML(w)
})
output$nameElem <-renderUI({
elems=c("<div>")
for(i in 1:input$elemNb){
elems=paste(elems,"</div><div>",input[[paste0("elemName",i)]])
}
elems=paste0(elems,"</div>")
HTML(elems)
})
}
runApp(list(ui = ui, server = server))
Found a solution:
library(readr)
library(dplyr)
library(shiny)
df <- data.frame(symbol = 1:10)
uiOutput("myUI")
createUI <- function(dfID, symbol) {
div(class="flex-box",paste0(symbol, " - 10"))
}
output$myUI <- renderUI({
w <- lapply(seq_len(nrow(df)), function(i) {
createUI(i, df[i,"symbol"])
})
do.call(fluidPage,w)
})