Resetting modal when closing it in a shiny app - r

I have a shiny app where a datatable is displayed. There is a column with a checkbox that allows the user to select the row and when pressing a button a modal is displayed. The modal contains a table with a subset of the datatable including only the row selected (my real app triggers another function but the effect is the same)
However, when the user deselects the row and selects another row, the previous content in the model is displayed before being replaced with the new one.
Is there any way of resetting the model everytime the button is pressed?
Here is the code I am using:
library(shinydashboard)
library(shinydashboardPlus)
library(shiny)
library(flextable)
data(mtcars)
header <- dashboardHeader()
sidebar <- dashboardSidebar()
body <- dashboardBody(
fluidPage(
tags$head(tags$style("#modal1 .modal-body {padding: 10px}
#modal1 .modal-content {-webkit-border-radius: 12px !important;-moz-border-radius: 12px !important;border-radius: 12px !important;}
#modal1 .modal-dialog { width: 800px; display: inline-block; text-align: left; vertical-align: top;}
#modal1 .modal-header {background-color: #339FFF; border-top-left-radius: 6px; border-top-right-radius: 6px}
#modal1 .modal { text-align: center; padding-right:10px; padding-top: 24px;}
#moda1 .close { font-size: 16px}")),
tags$script(HTML('$(".modal").on("hidden.modal1", function(){
$(this).removeData();
});'
)
),
fluidRow(
column(2,offset = 2,
HTML('<div class="btn-group" role="group" aria-label="Basic example">'),
actionButton(inputId = "Compare_row_head",label = "Get full data"),
HTML('</div>')
),
column(12,dataTableOutput("tabla")),
tags$script(HTML('$(document).on("click", "input", function () {
var checkboxes = document.getElementsByName("row_selected");
var checkboxesChecked = [];
for (var i=0; i<checkboxes.length; i++) {
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i].value);
}
}
Shiny.onInputChange("checked_rows",checkboxesChecked);})')
),
tags$script("$(document).on('click', '#Main_table button', function () {
Shiny.onInputChange('lastClickId',this.id);
Shiny.onInputChange('lastClick', Math.random())
});")
)
)
)
ui <- dashboardPagePlus(enable_preloader = TRUE, sidebar_fullCollapse = TRUE, header, sidebar, body)
## Server side
server = function(input, output, session) {
data("mtcars")
# Reactive function creating the DT output object
output$tabla <- renderDataTable({
req(mtcars)
data <- mtcars
data
data[["Select"]]<-paste0('<input type="checkbox" name="row_selected" value="Row',1:nrow(data),'"><br>')
datatable(data, escape = FALSE)
})
###Modal visualisation
observeEvent(input$Compare_row_head,{
showModal(tags$div(id="modal1", annotation_modal1))
}
)
annotation_modal1<-modalDialog(
fluidPage(
h3(strong("Example modal"),align="left"),
uiOutput('disTable')
),
size="l"
)
output$disTable <- renderUI({
req(input$checked_rows)
row_to_sel=as.numeric(gsub("Row","",input$checked_rows))
if (length(row_to_sel)){
#if (length(s)) {
#df <- vals$fake_sales
df <- mtcars
df <- as.data.frame(df[row_to_sel,])
ft <- flextable(df)
ft <- flextable::bold(ft, part="header")
ft <- flextable::autofit(ft)
ft <- flextable::width(ft, j=2, width=.1)
ft <- flextable::align(ft, align = "left", part = "all" )
ft %>% htmltools_value()
}
})
} # Server R
shinyApp(ui, server)
In the code pasted above I have tried to reset the modal using this:
tags$script(HTML('$(".modal").on("hidden.modal1", function(){
$(this).removeData();
});'
)
)
But it doesn't work
Thanks

The problem here is, that disTable only is rendered when your modalDialog is triggered (not already when the boxes are checked).
We can force shiny to render disTable earlier (when input$checked_rows is changed) by setting:
outputOptions(output, "disTable", suspendWhenHidden = FALSE)
Please check the following:
library(shinydashboard)
library(shinydashboardPlus)
library(shiny)
library(DT)
library(flextable)
data(mtcars)
header <- dashboardHeader()
sidebar <- dashboardSidebar()
body <- dashboardBody(
fluidPage(
tags$head(tags$style("#modal1 .modal-body {padding: 10px}
#modal1 .modal-content {-webkit-border-radius: 12px !important;-moz-border-radius: 12px !important;border-radius: 12px !important;}
#modal1 .modal-dialog { width: 800px; display: inline-block; text-align: left; vertical-align: top;}
#modal1 .modal-header {background-color: #339FFF; border-top-left-radius: 6px; border-top-right-radius: 6px}
#modal1 .modal { text-align: center; padding-right:10px; padding-top: 24px;}
#moda1 .close { font-size: 16px}")),
fluidRow(
column(2,offset = 2,
HTML('<div class="btn-group" role="group" aria-label="Basic example">'),
actionButton(inputId = "Compare_row_head",label = "Get full data"),
HTML('</div>')
),
column(12,dataTableOutput("tabla")),
tags$script(HTML('$(document).on("click", "input", function () {
var checkboxes = document.getElementsByName("row_selected");
var checkboxesChecked = [];
for (var i=0; i<checkboxes.length; i++) {
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i].value);
}
}
Shiny.onInputChange("checked_rows",checkboxesChecked);})')
),
tags$script("$(document).on('click', '#Main_table button', function () {
Shiny.onInputChange('lastClickId',this.id);
Shiny.onInputChange('lastClick', Math.random())
});")
)
)
)
ui <- dashboardPagePlus(enable_preloader = TRUE, sidebar_fullCollapse = TRUE, header, sidebar, body)
## Server side
server = function(input, output, session) {
data("mtcars")
# Reactive function creating the DT output object
output$tabla <- renderDataTable({
req(mtcars)
data <- mtcars
data
data[["Select"]]<-paste0('<input type="checkbox" name="row_selected" value="Row',1:nrow(data),'"><br>')
datatable(data, escape = FALSE)
})
###Modal visualisation
observeEvent(input$Compare_row_head,{
showModal(tags$div(id="modal1", annotation_modal1))
}
)
annotation_modal1 <- modalDialog(
fluidPage(
h3(strong("Example modal"), align="left"),
uiOutput('disTable')
),
size="l"
)
output$disTable <- renderUI({
req(input$checked_rows)
row_to_sel=as.numeric(gsub("Row", "", input$checked_rows))
if (length(row_to_sel)){
#if (length(s)) {
#df <- vals$fake_sales
df <- mtcars
df <- as.data.frame(df[row_to_sel,])
ft <- flextable(df)
ft <- flextable::bold(ft, part="header")
ft <- flextable::autofit(ft)
ft <- flextable::width(ft, j=2, width=.1)
ft <- flextable::align(ft, align = "left", part = "all" )
ft %>% htmltools_value()
}
})
outputOptions(output, "disTable", suspendWhenHidden = FALSE)
} # Server R
shinyApp(ui, server)

Related

Move previous next buttons in R's slickR carousel

I can successfully move the "next" button for slickR's carousel. However, when I use the similar method to move the "previous" button it does not work. The action and the mouseover no longer work. Why is this? How can I move the "prev" button and maintain full functionality?
The documentation refers to an element in settings called, appendArrows. But it is not clear to me how to use this.
appendArrows character, Change where the navigation arrows are attached (Selector, htmlString, Array, Element, jQuery object), Default: $(element)
Here is where the fully functional moved buttons should appear:
library(shiny)
library(slickR)
# Test #########################################################################
chart_names_list <- c( "http://placehold.it/900x500/39CCCC/ffffff&text=Slide+1",
"http://placehold.it/900x500/39CCCC/ffffff&text=Slide+2",
"http://placehold.it/900x500/39CCCC/ffffff&text=Slide+3")
num_slides <- 2
ui <- fluidPage(
tags$head(
tags$style(HTML("
.slick-next {
right: 163px;
top: 20px;
}
.slick-prev {
left: 670px;
top: 20px;
}
.slick-slide {
margin-top: 30px;
}
")
)
),
slickROutput("slick_output")
)
server <- function(input, output, session) {
output$slick_output <- renderSlickR({
slickR(obj = chart_names_list, height = 300, width = "100%") +
settings(dots = TRUE)
})
}
shinyApp(ui, server)
appendArrows parameter is used to tell in which div class the arrows should be displayed.
This shows the principle, but still needs some extra css to get exactly the result you expect :
library(shiny)
library(slickR)
# Test #########################################################################
chart_names_list <- c( "http://placehold.it/900x500/39CCCC/ffffff&text=Slide+1",
"http://placehold.it/900x500/39CCCC/ffffff&text=Slide+2",
"http://placehold.it/900x500/39CCCC/ffffff&text=Slide+3")
num_slides <- 2
ui <- fluidPage(
tags$head(
tags$style(HTML("
.arrows {
height: 30px;}"))
),
fluidRow(
column(6,),
column(2,
tags$div(class="arrows"
)),column(4)),
slickROutput("slick_output")
)
server <- function(input, output, session) {
output$slick_output <- renderSlickR({
slickR(obj = chart_names_list, height = 300, width = "100%") +
settings(dots = TRUE, appendArrows = '.arrows')
})
}
shinyApp(ui, server)
Taking #Waldi's valuable suggestions and adding some css leads to a complete answer below.
library("shiny")
library("slickR")
# Test #########################################################################
chart_names_list <- c( "http://placehold.it/900x500/39CCCC/ffffff&text=Slide+1",
"http://placehold.it/900x500/39CCCC/ffffff&text=Slide+2",
"http://placehold.it/900x500/39CCCC/ffffff&text=Slide+3")
num_slides <- 3
ui <- fluidPage(
tags$head(
tags$style(HTML("
.arrows {
height: 30px;
}
.slick-prev {
left: 230px; # moves right
}
.slick-next {
left: 250px; # moves right
}
"))
),
fluidRow(
column(6,),
column(2,
tags$div(class="arrows"
)),
column(4)),
slickROutput("slick_output")
)
server <- function(input, output, session) {
output$slick_output <- renderSlickR({
slickR(obj = chart_names_list, height = 300, width = "100%") +
settings(dots = TRUE, appendArrows = '.arrows')
})
}
shinyApp(ui, server)
As this is the original question regarding the positioning of the arrow buttons, I guess it's worth mentioning, that #ixodid realized here, that #Waldi's column-approach is no longer working when the browser window is resized.
The following is a workaround regarding this:
library("shiny")
library("slickR")
chart_names_list <- c( "http://placehold.it/900x500/39CCCC/ffffff&text=Slide+1",
"http://placehold.it/900x500/39CCCC/ffffff&text=Slide+2",
"http://placehold.it/900x500/39CCCC/ffffff&text=Slide+3")
num_slides <- 3
ui <- fluidPage(
tags$head(
tags$style(HTML("
.arrows {
height: 20px;
}
.slick-prev {
left: calc(100% - 60px);
}
.slick-next {
left: calc(100% - 35px);
}
.slick-slide img {
width: 100% !important;
}
"))
),
fluidRow(
column(12, tags$div(class="arrows"))
),
slickROutput("slick_output")
)
server <- function(input, output, session) {
output$slick_output <- renderSlickR({
slickR(obj = chart_names_list, height = 300) +
settings(dots = TRUE, appendArrows = '.arrows')
})
}
shinyApp(ui, server)

How can I display a dataframe in a Shiny app as a grid, and not a table?

I have some data in a dataframe. I can display the dataframe as a table with DataTables.
However, I would like to display the data as a grid with N columns, so that every N rows from the data frame are shown in the same row.
Show data as a grid:
As shown in the image above, I have gotten a grid to show up by using HTML to render the data frame directly.
But the next step is where I am stuck, which is I want to be able to show a modal dialog when a cell in the grid is clicked.
I have that working in the data table, but I haven't been able to figure out how to make a div clickable, such that when handling the event I know which cell was clicked?
library("shiny")
library("tidyr")
library("tidyverse")
library("dplyr")
library("shinydashboard")
# generate html grid from data frame
getHTML <- function (frames) {
innerhtml = '<div class="grid-container">'
for (row in 1:(nrow(frames))) {
id <- frames[row, "id"]
name <- frames[row, "names"]
row_html = '<div class="grid-item">'
row_html = paste(row_html, '<span>Name: ' , name, "id ", row , '</span>')
row_html = paste(row_html, '</div>')
innerhtml = paste(innerhtml, row_html)
}
paste(innerhtml, "</div>")
return (innerhtml)
}
#show modal dialog for player id and name
plotModal <- function(id, name) {
modalDialog(
p(paste("Player # ", id, ", " , name,", was clicked")),
title = paste("Player " , id),
easyClose = TRUE
)
}
ui <- dashboardPage(
# Application title
dashboardHeader(title = "Dashboard"),
dashboardSidebar(
h3("Filters")
),
dashboardBody(
tags$head(tags$style(HTML('
.grid-container {
display: grid;
grid-template-columns: auto auto auto auto;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 20px;
}'))),
fluidRow(
box(title="Render as table", column(width=12, DT::dataTableOutput("player_table"))),
box(title="Render as Grid", column(width=12, uiOutput("player_grid")))
)
)
)
server <- function(input, output, session) {
# data to be rendered
frames = data.frame(names= c("james","kyle", "sally","hannah","jeff","kurt"), ids=c(1:6))
output$player_table <- DT::renderDataTable({
DT::datatable(frames, rownames=FALSE, selection = 'single')
})
#when a row in the table is clicked, show popup
observeEvent(input$player_table_cell_clicked, {
info = input$player_table_cell_clicked
# do nothing if not clicked yet, or the clicked cell is not in the 1st column
if (is.null(info$value)) {
return()
}
row = frames[info$row, ]
showModal(plotModal(row$id, row$names))
})
output$player_grid <- renderUI ({
HTML(getHTML(frames))
})
}
# Create Shiny app ----
shinyApp(ui, server,options=list(host="0.0.0.0", port=8015))
Here is a way:
library(shiny)
library(shinydashboard)
js <- "
$(document).ready(function(){
$('body').on('click', '.grid-item span', function(){
var name = $(this).data('name'),
id = $(this).data('id');
Shiny.setInputValue('cell', {name: name, id: id});
});
});
"
# generate html grid from data frame
getHTML <- function (frames) {
innerhtml = '<div class="grid-container">'
for (row in 1:(nrow(frames))) {
id <- frames[row, "ids"]
name <- frames[row, "names"]
row_html = '<div class="grid-item">'
cell <- sprintf("<span data-name='%s' data-id='%s'>Name: %s - id: %s</span>",
name, id, name, id)
row_html = paste(row_html, cell)
row_html = paste(row_html, '</div>')
innerhtml = paste(innerhtml, row_html)
}
paste(innerhtml, "</div>")
return (innerhtml)
}
#show modal dialog for player id and name
plotModal <- function(id, name) {
modalDialog(
p(paste("Player # ", id, ", " , name,", was clicked")),
title = paste("Player " , id),
easyClose = TRUE
)
}
ui <- dashboardPage(
# Application title
dashboardHeader(title = "Dashboard"),
dashboardSidebar(
h3("Filters")
),
dashboardBody(
tags$head(tags$style(HTML('
.grid-container {
display: grid;
grid-template-columns: auto auto auto auto;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 20px;
}')),
tags$script(HTML(js))),
fluidRow(
box(title="Render as Grid", column(width=12, uiOutput("player_grid")))
)
)
)
server <- function(input, output, session) {
# data to be rendered
frames = data.frame(
names= c("james","kyle", "sally","hannah","jeff","kurt"),
ids=c(1:6)
)
#when a row in the table is clicked, show popup
observeEvent(input$cell, {
showModal(plotModal(input$cell$id, input$cell$name))
})
output$player_grid <- renderUI ({
HTML(getHTML(frames))
})
}
# Create Shiny app ----
shinyApp(ui, server)

Move R Shiny showNotification to a certain div

Closely related to this question, I am trying to move the showNotification´s to a certain div that is already on the page. Is there an easy way to do that?
The following app should illustrate the problem. The notifications in the lower right should go in the yellow div.
library(shiny)
ui=shinyUI(fluidPage(
tags$head(
tags$style(HTML("
#error {
width: 100%;
border: black 1px solid;
padding: 5px;
margin: 10px 0;
background-color: #f7f2d9;
}
"))
),
sidebarLayout(
sidebarPanel(
sliderInput("lambda","Number",min = 1,max = 100,value = 27)
),
mainPanel(
h3("Move the slider above 28 to trigger a Notification! "),
plotOutput("algebra"),
div(id = "error", p("The notifications should appear in here")),
tableOutput('table')
)
)
))
server=function(input, output) {
output$algebra <- renderPlot({
if (input$lambda > 28){
showNotification("How can I put this message in the #error div?", id = "error", type = "warning", duration = NULL)
return(NULL)
}
n <- 1:100
lambda <- seq(min(n), max(n), length.out = input$lambda)
plot((2*lambda)+3, type = "o",xlab= "X (number of data points)", ylab = "Y = 2x+3")
})
output$table <- renderTable(iris)
}
shinyApp(ui,server)
This seems to work:
library(shiny)
library(shinyjs)
ui=shinyUI(fluidPage(
useShinyjs(),
tags$head(
tags$style(HTML("
#error {
width: 100%;
border: black 1px solid;
padding: 5px;
margin: 10px 0;
background-color: #f7f2d9;
}
#shiny-notification-panel {
position: static;
}
"))
),
......
and in server:
output$algebra <- renderPlot({
if(input$lambda > 28){
showNotification("How can I put this message in the #error div?", type = "warning", duration = NULL)
runjs('setTimeout(function(){$("#error").append($("#shiny-notification-panel"))},0);')
return(NULL)
}
......
Not highly tested though. An alternative is bsAlert from the shinyBS package.

observers fire on render of dynamic UI when they should not

The problem I face is that observers linked to dynamically rendered elements seem to fire on render, while this is not how I want it to be.
The reason this is a problem, is that the color buttons I'm making are linked to a plot that takes several seconds to render (plotly widget)
I added ignoreInit = T the observers that are created, but they still fire on rendering, unlike normal observers linked to a button build directly in the UI
How do I stop the observers linked to the dynamically rendered colourInput from firing when the element is rendered?
In the dummy app below the following series of events is recreated in simplified form:
A model spits out a number (simulated by test button in demo app)
Based on this number, a number of colourInput buttons are made
A same number of observeEvents are made for each.
Not in the dummy app: When the user chooses to change a color, the corresponding group in plots is recolored accordingly
The test app contains a working static colourInput, and a dynamic part that demonstrates the problem scenario.
Test app:
library(shiny)
library("colourpicker")
THECOLORS <- c('#383838', '#5b195b','#1A237E', '#000080', '#224D17', '#cccc00', '#b37400', '#990000',
'#505050', '#a02ca0', '#000099', '#2645e0', '#099441', '#e5e500', '#cc8400', '#cc0000',
'#737373', '#e53fe5', '#0000FF', '#4479e1', '#60A830', '#ffff00','#e69500', '#ff0000',
'#b2b2b2', '#eb6ceb', '#6666ff', '#d0a3ff', '#9FDA40', '#ffff7f', '#ffa500', '#ff4c4c')
ui <- fluidPage(
h1("WELCOME TO THE TEST APP", style = 'text-align: center; font-weight:bold' ),
br(),
h3("STATIC PART: doesn't fire on startup, great!", style = 'font-weight:bold'),
div(colourpicker::colourInput(inputId = 'StaticColor', label = NULL, palette = "limited", allowedCols = THECOLORS, value = THECOLORS[14], showColour = "background", returnName = TRUE),
style = " height: 30px; width: 30px; border-radius: 6px; border-width: 2px; text-align:center; padding: 0px; display:block; margin-bottom: 10px"),
br(),
h3("Dynamic part: fires on render, NOT great!", style = 'font-weight:bold'),
actionButton(inputId = 'Tester', label = 'Click me'),
br(),
uiOutput('colorbutton')
)
server <- function(input, output, session) {
values <- reactiveValues()
values$mycolors <- THECOLORS
observeEvent(input$Tester, { values$NrofButtons <- sample(1:10, 1) })
observeEvent(values$NrofButtons, {
COLElement <- function(idx){sprintf("COL_button-%s-%d",values$NrofButtons,idx)}
output$colorbutton <- renderUI({
lapply(1:values$NrofButtons, function(x) {
div(colourpicker::colourInput(inputId = COLElement(x), label = NULL, palette = "limited", allowedCols = values$mycolors, value = values$mycolors[x], showColour = "background", returnName = TRUE),
style = " height: 30px; width: 30px; border-radius: 6px; border-width: 2px; text-align:center; padding: 0px; display:block; margin-bottom: 10px") })
})
lapply(1:values$NrofButtons, function(x) { observeEvent(input[[COLElement(x)]], { print(input[[COLElement(x)]] )}, ignoreInit = T) }) # make observer for each button
})
observeEvent(input[['StaticColor']], { print(input[['StaticColor']] )}, ignoreInit = T)
}
shinyApp(ui,server)
Renders should always be by themselves and be data driven, not event driven -- so I've made the render require the number of colors to be defined before rendering. Of course the number of colors aren't defined until the observeEvent is fired by clicking the button.
Overall there is still the issue that every time the button is clicked more observers are created for the same ID, working on a way to destroy these automatically on a subsequent click of the tester button.
The key addition was a ignoreInit = TRUE in your observeEvent(input$Tester, {...}) observer.
library(shiny)
library("colourpicker")
THECOLORS <- c('#383838', '#5b195b','#1A237E', '#000080', '#224D17', '#cccc00', '#b37400', '#990000',
'#505050', '#a02ca0', '#000099', '#2645e0', '#099441', '#e5e500', '#cc8400', '#cc0000',
'#737373', '#e53fe5', '#0000FF', '#4479e1', '#60A830', '#ffff00','#e69500', '#ff0000',
'#b2b2b2', '#eb6ceb', '#6666ff', '#d0a3ff', '#9FDA40', '#ffff7f', '#ffa500', '#ff4c4c')
ui <- fluidPage(
h1("WELCOME TO THE TEST APP", style = 'text-align: center; font-weight:bold' ),
br(),
h3("STATIC PART: doesn't fire on startup, great!", style = 'font-weight:bold'),
div(colourpicker::colourInput(inputId = 'StaticColor', label = NULL, palette = "limited", allowedCols = THECOLORS, value = THECOLORS[14], showColour = "background", returnName = TRUE),
style = " height: 30px; width: 30px; border-radius: 6px; border-width: 2px; text-align:center; padding: 0px; display:block; margin-bottom: 10px"),
br(),
h3("Dynamic part: fires on render, NOT great!", style = 'font-weight:bold'),
actionButton(inputId = 'Tester', label = 'Click me'),
br(),
uiOutput('colorbutton')
)
COLElement <- function(idx) sprintf("COL_button-%d", idx)
server <- function(input, output, session) {
values <- reactiveValues(previous_max = 1)
observeEvent(input$Tester, {
values$NrofButtons <- sample(1:10, 1)
# reset counters for all observers
for (i in seq(values$NrofButtons)) {
values[[sprintf("observer%d_renders", i)]] <- 0L
}
# only initialize incremental observers
lapply(values$previous_max:values$NrofButtons, function(x) {
observeEvent(input[[COLElement(x)]], {
# only execute the second time, since the `ignoreInit` isn't obeyed
if (values[[sprintf("observer%d_renders", x)]] > 0) {
print(input[[COLElement(x)]] )
} else {
values[[sprintf("observer%d_renders", x)]] <- 1L
}
}, ignoreInit = TRUE)
}) # make observer for each button
# record the max
values$previous_max <- max(values$previous_max, max(values$NrofButtons))
}, ignoreInit = TRUE)
output$colorbutton <- renderUI({
req(length(values$NrofButtons) > 0)
lapply(1:values$NrofButtons, function(x) {
div(colourpicker::colourInput(
inputId = COLElement(x)
, label = NULL
, palette = "limited"
, allowedCols = THECOLORS
, value = THECOLORS[x]
, showColour = "background"
, returnName = TRUE
)
, style = " height: 30px; width: 30px; border-radius: 6px; border-width: 2px; text-align:center; padding: 0px; display:block; margin-bottom: 10px"
)
})
})
observeEvent(input$StaticColor, {
print(input$StaticColor )
}, ignoreInit = TRUE)
}
shinyApp(ui,server)

R Shiny CondtionalPanel not using CSS stylesheet

I'm using R Shiny to build a web application.
I'm using conditionPanels to (sometimes) show a pivot table depending on the type of object df.
As shown below, if the pivot table is shown within a conditionalpanel, the css is simply ignored and the Pivot table is shown in default style. But if I include a second pivottable, not rendered in the conditionalpanel, both pivottables are in the style as described in the custom.css.
How can I make sure that the stylesheet is used for the first pivottable when there is not second one?
# Server.R
server <- shinyServer(function(input, output,session){
df <- data.frame(col1 = c('a','b','c'),
col2 = c(1,2,3))
## Output PivotTable
output$pivotTable <- rpivotTable::renderRpivotTable({
rpivotTable(data = df,
aggregatorName = 'Sum',
rendererName = 'Table')
})
## Output PivotTable2
output$pivotTable2 <- rpivotTable::renderRpivotTable({
rpivotTable(data = df,
aggregatorName = 'Sum',
rendererName = 'Table')
})
condition <- ifelse(is.data.frame(df), 'true', 'false')
## Output PivotTable
output$panelTable <- renderUI({
conditionalPanel(
condition,
rpivotTableOutput("pivotTable")
)
})
})
# UI.R:
ui <- dashboardPage(
title = "",
## Header content + dropdownMenu
dashboardHeader(
title = tags$b(""),
titleWidth = 250
),
## Sidebar content
dashboardSidebar(
width = 250,
sidebarMenu(
id = "tabs",
menuItem("tab1", tabName = "tab", icon = icon("table"))
)
),
## Body content
dashboardBody(
tags$head(tags$link(rel = "stylesheet", type = "text/css", href = "custom.css")),
tabItems(
tabItem(tabName = "tab",
div(
uiOutput('panelTable')
),
div(
rpivotTableOutput("pivotTable2")
)
)
)
)
)
# Create Shiny object
shinyApp(ui = ui, server = server)
CSS:
/* Adjust css of pivot table */
#pivotTable{
overflow-x: scroll;
overflow-y: scroll;
}
.pvtRows, .pvtCols {
background: #FAFAFA none repeat scroll 0 0;
}
table.pvtTable tbody tr th, table.pvtTable thead tr th {
background: #FFFFFF;
}
.pvtAxisContainer li span.pvtAttr {
background: rgba(147,255,53,0.8);
}
HI your problem is that your css is being overruled from css rules generated be pivotTable to over rule this add !important after each rule like this
#pivotTable{
overflow-x: scroll;
overflow-y: scroll;
}
.pvtRows, .pvtCols {
background: #FAFAFA none repeat scroll 0 0 !important;
}
table.pvtTable tbody tr th, table.pvtTable thead tr th {
background: #FFFFFF!important;
}
.pvtAxisContainer li span.pvtAttr {
background: rgba(147,255,53,0.8) !important;
}
hope this helps!
I think you can try to define class inside the div's.
For example:
div(class = "pvtRows pvtAxisContainer",
uiOutput('panelTable')
)

Resources