How to make shiny print good looking messages to user interface


#1

Hello!

First of all: anybody could tell me how to paste code snippets in posts? Mine seem to behave randomly… The only way I figured out is putting 4 spaces in each row - but there must be a simpler way.

I have a simple shiny app. First, I generated 2 csv files in my working directory:

write.csv(data.frame(a = 1:4, b = 2:5), "x.csv", row.names = F)
write.csv(data.frame(a = 1:4, c = 11:14), "y.csv", row.names = F)

In my app, I want the user to:

  1. read in 2 files (x.csv and y.csv) and…
  2. Click on the button ‘Run’!
  3. After that I want server.R to write out 2 csv files - but also to print out certain messages for the user to see.

My code below works, but currently the messages for the user look very ugly and each is sitting on a dull gray background.
Two questions:

  1. Is my method the only method to print messages for the user? Or maybe there is a more elegant one?
  2. How could I modify the gray background, font size, color, etc?

Thank you so much!

library(shiny)
library(shinyjs)

# ui code:

ui <- fluidPage(

  useShinyjs(),
  br(),
       # User should upload file x.csv here:
     fileInput("file_x", label = h5("Upload file 'x.csv'!")),
  br(),
      # User should upload file y.csv here:
  fileInput("file_y", label = h5("Upload file 'y.csv'!")),
  br(),
      # Users clicks the button:
  actionButton("do_it", "Run!"),
  br(),
  hidden(p("First, please upload one of the 2 files above!",
           id = "p_nofiles",
           style = "font-weight:bold;color:red;")),
  br(),
  verbatimTextOutput("message_1"),
  br(),
  verbatimTextOutput("message_2"),
  br(),
  verbatimTextOutput("message_3")

)

# server code:

    server <- function(input, output, session) {

      observeEvent(input$do_it, {

    # If there file_x input is NULL, show the message in p_nofile
    if (is.null(input$file_x) | is.null(input$file_y)) {
      shinyjs::show("p_nofiles")
    } else {
      # if both files are selected, hide the p_nofiles message
      shinyjs::hide("p_nofiles")

      # Check my button's value:
      output$print_action <- renderPrint({input$do_it})

      # Read in file x_csv:
      infileX <- input$file_x
      if (is.null(infileX)) {  
        return(NULL)     
        }
      x <- read.csv(infileX$datapath)

      # Read in file y_csv:
      infileY <- input$file_y
      if (is.null(infileY)) {  
        return(NULL)     
      }
      y <- read.csv(infileY$datapath)

      #-------------------------------------------------------------------------------------------
      # MESSAGES I WANT THE USER TO SEE:

      # MESSAGE 1 - always there: What names do x and y have in common?
      mes1 <- paste0("x and y have these columns in common: ", 
                     intersect(names(x), names(y)), "\n")
      output$message_1 <- renderText({mes1})

      # MESSAGE 2 - with 2 alternative texts: Do x and y have the same number of rows?
      if (nrow(x) == nrow(y)) { 
        mes2 <- "x and y have the same number of rows!\n"
      } else {
          mes2 <- "x has a different number of rows than y\n"
      }
      output$message_2 <- renderText({mes2})

      # MESSAGE 3 - to be printed only under one condition:
      # Do x and y have a different number of columns? Print only it's different, otherwise - nothing
      if (ncol(x) != ncol(y)) { 
        mes3 <- "x and y do NOT have the same number of columns!\n"
        output$message_3 <- renderText({mes3})
      } else {output$message_3 <- renderText({NULL})}

      #-------------------------------------------------------------------------------------------
      # Writing out the same file x - but under a different name:

      filenameX <- paste0("x", input$do_it, ".csv")
      write.csv(x, file = filenameX, row.names = FALSE)

       # Writing out the same file y - but under a different name:
      filenameY <- paste0("y", input$do_it, ".csv")
      write.csv(y, file = filenameY, row.names = FALSE)
    }
  })
}

shinyApp(ui, server)

#2

Did you get any response from the forum? Or did you solve the problem yourself. I am keen to see your final solution. Thanks.


#3

No, I didn't :frowning:


#4

You can modify the background color, font, etc. using css. For example, try putting these codes in your ui section.

  tags$style(type = 'text/css', '#message_1         {font-size: 12px; font-family: calibri light; background-color: rgba(255,255,255,0.40); color: black; border-style: none;}'), 
  tags$style(type = 'text/css', '#message_2         {font-size: 12px; font-family: calibri light; background-color: rgba(255,255,255,0.40); color: black; border-style: none;}'), 
  tags$style(type = 'text/css', '#message_3         {font-size: 12px; font-family: calibri light; background-color: rgba(255,255,255,0.40); color: black; border-style: none;}'), 

Another option to give a message to users it to use shinyalert. For example,

    shiny::observeEvent(input$do_it, {
      shinyalert::shinyalert("Your message here", type = "success", showConfirmButton = TRUE)
    })

Hope this helps!