shiny module: update color of button - r

i am struggling with the logic of updating a button in the ui based on code that is living in a module. When I click the button i want it to change the colour but nothing happens. I understand to make ui input reactive in order to use it in the server module but i do not get it working the other way around. Help (and some explanation) is highly appreciated!
here is my code: (I left the save to csv part upon click as i got that to work).
library(shiny)
library(shinyBS)
module_company_ui<-function(id){
# `NS(id)` returns a namespace function, which was save as `ns` and will
# invoke later.
ns <- NS(id)
tagList(
radioButtons(ns("company_name"), label= "Is the << COMPANY NAME >> correct?",
c("choose from below" = "10",
"correct" = "0.15",
"correct, but some noise" = "0.075",
"not sure" = "0.05",
"wrong" = "0"),selected = character(0)),
textOutput(ns("txt")),
bsButton(ns('save_inputs'), " Save", type="action", block=TRUE, style="info", icon=icon(name="save"))
)
}
module_save_inputs<-function(id, value_company){
moduleServer(
id,
## Below is the module function
function(input, output, session) {
save<-reactive(input$save_inputs)
observeEvent(save(), {
updateButton(session, "save_inputs",label = " Save", block = T, style = "success", icon=icon(name="save"))
})
})
}
ui <- fluidPage(
module_company_ui("company")
)
server <- function(input, output, session) {
module_save_inputs("company")
}
shinyApp(ui, server)

You need namespace ns for the updateButton. Try this
module_save_inputs<-function(id, value_company){
moduleServer(
id,
## Below is the module function
function(input, output, session) {
ns <- session$ns
save<-reactive(input$save_inputs)
observeEvent(save(), {
updateButton(session, ns("save_inputs"),label = " Save", block = T, style = "success", icon=icon(name="save"))
})
})
}

Related

How to Instantiate a ShinyReForms in a Shiny Module

Its quite quick and easy to instantiate a ShinyReForms for a Shiny app by following the example at https://piotrbajger.github.io/shinyreforms/articles/tutorial.html. I cannot though see how to get it working in a Shiny module.
The app below is a smaller version of the example app, presented in a module, and with an extra output which shows the result of the namespaced checkbox.
The ‘submit’ button doesn’t return the expected output though. I’m opining that this is a name space issue, though I can’t see where to wrap an id with something like... ns(“myformid”).
Any suggestions please. Thanks
library(shiny)
library(shinyreforms)
modUI <- function(id) {
ns <- NS(id)
tagList(
uiOutput(ns('form_ui')),
)
}
modServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
myForm <- shinyreforms::ShinyForm$new(
"myForm",
submit = "Submit",
onSuccess = function(self, input, output) {
yourName <- self$getValue(input, "name_input")
output$result <- shiny::renderText({
paste0("Your name is ", yourName, "!")
})
},
onError = function(self, input, output) {
output$result <- shiny::renderText({
"Form is invalid!"
})
},
shinyreforms::validatedInput(
shiny::checkboxInput(ns("checkbox"), label = "I accept!"),
validators = c(
shinyreforms::ValidatorRequired()
)
)
)
myForm$server(input, output)
output$ot_checkox <- renderUI({
h4(input$checkbox, style = 'color: blue;')
})
output$form_ui <- renderUI({
tagList(
shiny::tags$h1("Example ShinyForm!"),
myForm$ui(), # <- ShinyForm will be included here!
uiOutput(ns('ot_checkox')),
shiny::tags$h4("Result:"),
shiny::textOutput(ns("result"))
)
})
}
)
}
ui <- shiny::bootstrapPage(
shinyreforms::shinyReformsPage(
shiny::fluidPage(
modUI('mod_id')
)
)
)
server <- function(input, output, session) {
modServer('mod_id')
}
shinyApp(ui, server)

Testing if the module has been called in shiny

I write some shiny tests recently using testServer which is great in most of the scenarios. I'm thinking about following problem which I can't solve now.
Let's imagine simple modules (ui/server)
child_ui <- function(id) {
ns <- NS(id)
div(
selectInput(inputId = ns("select"), label = "select", choices = c("a", "b"), selected = "a"),
verbatimTextOutput(outputId = ns("out"))
)
}
child_srv <- function(id) {
moduleServer(id, function(input, output, session) {
output$out <- renderPrint(input$select)
})
}
... which are called inside of the other module but through the specific function call_child.
parent_ui <- function(id, module) {
ns <- NS(id)
div(
module(ns("parent"))
)
}
parent_srv <- function(id, module) {
moduleServer(id, function(input, output, session) {
call_child <- function(module) {
module(id = "parent")
NULL
}
call_child(module)
})
}
What I would like to do is to check whether child_srv has been called and I wonder if there is some way to deduct this. Preferred solution is to keep call_child untouched (maybe some evidences are in session object).
The only thing I can do is following:
testServer(
app = parent_srv,
args = list(module = child_srv),
expr = {
tinytest::expect_null(call_child(module = module))
})
# example app
shinyApp(
ui = parent_ui(id = "root", module = child_ui),
server = function(input, output, session)
parent_srv(id = "root", module = child_srv)
)
Does anyone has any advice how to properly test this scenario?

How can I call a module inside an observeEvent function (shiny)

I'm trying to set up a simple Card game in Shiny and therefore want to use
callModule(...) inside of observeEvent(input$..,{}), so I can call the same module with different events occurring.
Unfortunately this does not seem to work.
I know, that if I simply use observeEvent(input$...,{}) inside my module the code does work but than I would have to define similar models for all possible Events.
playingUI <- function(id) {
ns <- NS(id)
tagList(# Create market and hand output
uiOutput(ns("market")),
uiOutput(ns("hand")),
# Actionbutton to take cards
actionButton(ns("take"),
label = "TAKE"))
}
player_server <- function(input, output, session, cards) {
# Pickerinput for Market
output$market <- renderUI(tagList(
pickerInput(
inputId = session$ns("market1"),
label = "Market",
choices = cards$market,
multiple = TRUE
),
# Pickerinput for Hand
pickerInput(
inputId = session$ns("Hand"),
label = "Hand",
choices = cards$hand,
multiple = TRUE
)
))
}
taking_server <- function(input, output, id, cards) {
cards$hand <- c(cards$hand, "new")
}
ui <- fluidPage(playingUI('game'))
server <- function(input, output, session) {
# Define playing cards
cards <- reactiveValues(
# Define market
market = c("Camel", "Gold", "Diamond"),
# Define hand
hand = c("Diamond", "Silver")
)
callModule(player_server, 'game', cards)
# Wrap the module 'taking_server' inside observe - does not work
observeEvent(input$take, {
callModule(taking_server, 'game', cards)
})
}
shinyApp(ui = ui, server = server)

How do you pass parameters to a shiny app via URL

In web browsers you pass parameters to a website like
www.mysite.com/?parameter=1
I have a shiny app and I would like to use the parameter passed in to the site in calculations as an input. So is it possible to do something like www.mysite.com/?parameter=1 and then use input!parameter?
Can you provide any sample code or links?
Thank you
You'd have to update the input yourself when the app initializes based on the URL. You would use the session$clientData$url_search variable to get the query parameters. Here's an example, you can easily expand this into your needs
library(shiny)
shinyApp(
ui = fluidPage(
textInput("text", "Text", "")
),
server = function(input, output, session) {
observe({
query <- parseQueryString(session$clientData$url_search)
if (!is.null(query[['text']])) {
updateTextInput(session, "text", value = query[['text']])
}
})
}
)
Building off of daattali, this takes any number of inputs and does the assigning of values for you for a few different types of inputs:
ui.R:
library(shiny)
shinyUI(fluidPage(
textInput("symbol", "Symbol Entry", ""),
dateInput("date_start", h4("Start Date"), value = "2005-01-01" ,startview = "year"),
selectInput("period_select", label = h4("Frequency of Updates"),
c("Monthly" = 1,
"Quarterly" = 2,
"Weekly" = 3,
"Daily" = 4)),
sliderInput("smaLen", label = "SMA Len",min = 1, max = 200, value = 115),br(),
checkboxInput("usema", "Use MA", FALSE)
))
server.R:
shinyServer(function(input, output,session) {
observe({
query <- parseQueryString(session$clientData$url_search)
for (i in 1:(length(reactiveValuesToList(input)))) {
nameval = names(reactiveValuesToList(input)[i])
valuetoupdate = query[[nameval]]
if (!is.null(query[[nameval]])) {
if (is.na(as.numeric(valuetoupdate))) {
updateTextInput(session, nameval, value = valuetoupdate)
}
else {
updateTextInput(session, nameval, value = as.numeric(valuetoupdate))
}
}
}
})
})
Example URL to test: 127.0.0.1:5767/?symbol=BBB,AAA,CCC,DDD&date_start=2005-01-02&period_select=2&smaLen=153&usema=1
Shiny App: How to Pass Multiple Tokens/Parameters through URL
The standard delimeter for tokens passed through url to shiny app is the & symbol.
Example shiny app code:
server <- function(input, output, session) {
observe({
query <- parseQueryString(session$clientData$url_search)
if (!is.null(query[['paramA']])) {
updateTextInput(session, "InputLabel_A", value = query[['paramA']])
}
if (!is.null(query[['paramB']])) {
updateTextInput(session, "InputLabel_A", value = query[['paramB']])
}
})
# ... R code that makes your app produce output ..
}
Coresponding URL example:
http://localhost.com/?paramA=hello&?paramB=world
Reference: parseQueryString Docs
Building off DeanAttali's idea, this snippet will re-generate the URL at the top so that users can copy the link for sharing to others.
The stringr:: part can probably be enhanced to be more URL-friendly.
library(stringr)
library(glue)
library(shiny)
# http://127.0.0.1:8080/?text=hello+world+I%27m+a+shiny+app
shinyApp(
ui = fluidPage(
textOutput("url"),
textInput("text", "Text", ""),
),
server = function(input, output, session) {
observe({
query <- parseQueryString(session$clientData$url_search)
if (!is.null(query[['text']])) {
updateTextInput(session, "text", value = query[['text']])
}
})
output$url <- renderText({
stringr::str_replace_all(glue::glue("http://127.0.0.1:8080/?text={input$text}"), ' ', '+')
})
},
options=list(port=8080)
)

Capture the label of an actionButton once it is clicked

Is it possible to capture the label of an actionButton once it is clicked?
Imagine I have 3 buttons on my ui.R and depending on which one I click I want to perform a different action on the server.R.
One caveat is that the buttons are created dynamically on the server.R with dynamic labels (thus the necessity of capturing the label on click)
Thanks
Something like that ?
library(shiny)
server <- function(input, session, output) {
output$printLabel <- renderPrint({input$btnLabel})
}
ui <- fluidPage(
actionButton("btn1", "Label1",
onclick = "Shiny.setInputValue('btnLabel', this.innerText);"),
actionButton("btn2", "Label2",
onclick = "Shiny.setInputValue('btnLabel', this.innerText);"),
verbatimTextOutput("printLabel")
)
shinyApp(ui = ui, server = server)
1) What button was clicked last by the user?
To answer this you can user observeEvent function and by setting up a a variable using reactiveValues function. Make sure you update your libraries and work in the latest version of R (version 3.1.3) as shiny is dependant on this version. Working on windows you can follow example on how to update here
rm(list = ls())
library(shiny)
ui =fluidPage(
sidebarPanel(
textInput("sample1", "Name1", value = "A"),
textInput("sample2", "Name2", value = "B"),
textInput("sample3", "Name3", value = "C"),
div(style="display:inline-block",uiOutput("my_button1")),
div(style="display:inline-block",uiOutput("my_button2")),
div(style="display:inline-block",uiOutput("my_button3"))),
mainPanel(textOutput("text1"))
)
server = function(input, output, session){
output$my_button1 <- renderUI({actionButton("action1", label = input$sample1)})
output$my_button2 <- renderUI({actionButton("action2", label = input$sample2)})
output$my_button3 <- renderUI({actionButton("action3", label = input$sample3)})
my_clicks <- reactiveValues(data = NULL)
observeEvent(input$action1, {
my_clicks$data <- input$sample1
})
observeEvent(input$action2, {
my_clicks$data <- input$sample2
})
observeEvent(input$action3, {
my_clicks$data <- input$sample3
})
output$text1 <- renderText({
if (is.null(my_clicks$data)) return()
my_clicks$data
})
}
runApp(list(ui = ui, server = server))
2) Save the clicks for further manipulation is below
Here's small example based on the work of jdharrison from Shiny UI: Save the Changes in the Inputs and the shinyStorage package.
rm(list = ls())
#devtools::install_github("johndharrison/shinyStorage")
library(shinyStorage)
library(shiny)
my_clicks <- NULL
ui =fluidPage(
#
addSS(),
sidebarPanel(
textInput("sample_text", "test", value = "0"),
uiOutput("my_button")),
mainPanel(uiOutput("text1"))
)
server = function(input, output, session){
ss <- shinyStore(session = session)
output$my_button <- renderUI({
actionButton("action", label = input$sample_text)
})
observe({
if(!is.null(input$sample_text)){
if(input$sample_text != ""){
ss$set("myVar", input$sample_text)
}
}
})
output$text1 <- renderUI({
input$action
myVar <- ss$get("myVar")
if(is.null(myVar)){
textInput("text1", "You button Name")
}else{
textInput("text1", "You button Name", myVar)
}
})
}
runApp(list(ui = ui, server = server))

Resources