I have been working with shinyBS to create a set of collapsible panels. In the one shown below, only one panel should be open at a time (since the parameter multiple defaults to FALSE), but all three can be opened at the same time.
ui.R
library(shiny)
library(shinyBS)
shinyUI(fluidPage(
bsCollapse(
id = "stuff.all",
bsCollapsePanel(title = "Load Data", "Load the files"),
bsCollapsePanel(title = "Set Parameters", "Set the parameters"),
bsCollapsePanel(title = "Teacher Settings", "Choose the teachers")
)
))
server.R
library(shiny)
library(shinyBS)
shinyServer(function(input, output) {})
What is causing this bsCollapse to act as though multiple = TRUE, and how can I prevent it in the future?
Reference: https://ebailey78.github.io/shinyBS/docs/Collapses.html
I actually figured this out while writing the question, so I plan to answer my own question.
The id for bsCollapse in my example was "stuff.all". The fact that a period was part of the id seems to be what created the problem. When I changed the id to "stuff", the problem went away. When the id is "stuff.al" or "stuff.a", the problem persists. When the id is "stuff." or ".stuff", none of the panels expand when clicked. Given the way that bsCollapse works, the problem arises either from having a period in the id of an HTML <div> tag like so:
<div class="panel-group sbs-panel-group" data-sbs-multi="FALSE" id="stuff.a" role="tablist">
or from having a period in the data-toggle of an HTML <a> tag, like so:
<a data-toggle="collapse" href="#cpanel0758223" data-parent="#stuff.a">Load Data</a>
Related
I want to use shiny.i18n in my app, which uses tooltips to provide more information on certain elements (using two types of tooltips, either with tipify or bsTooltip). However, I could not find how to integrate both, and the tooltips are not rendered properly.
As an example, this:
library(shiny)
library(shinyjs)
library(shinyBS)
library(shiny.i18n)
i18n <- Translator$new(translation_csvs_path = "data_translation/")
i18n$set_translation_language("en")
ui <- fluidPage(
useShinyjs(),
shiny.i18n::usei18n(i18n),
div(style = "float: left;",
selectInput('selected_language',
i18n$t("Change language"),
choices = i18n$get_languages(),
selected = i18n$get_key_translation())
),
mainPanel(
i18n$t("This is some text without a tooltip"),
textOutput("Text"),
bsTooltip("Text",
i18n$t("This is some text"),
placement="right", trigger = "hover", options=list(container="body")),
tipify(
actionButton("Button", "", icon = icon("house-user")),
i18n$t("This is a button"),
placement="right", trigger = "hover", options=list(container="body"))
))
server <- function(input, output, session) {
observeEvent(input$selected_language, {
shiny.i18n::update_lang(session, input$selected_language)
})
output$Text <- renderText({i18n$t("This is some text with a tooltip")})
}
shinyApp(ui, server)
file translate_fr.csv:
"en","fr"
"Hello","Bonjour"
"This is some text without a tooltip","Ceci est un texte sans tooltip"
"This is some text with a tooltip","Ceci est un texte avec tooltip"
"This is a button", "Ceci est un bouton"
"This is some text", "Ceci est un texte"
"Change language","Changer de langue"
returns:
While the tooltip should just contain "This is a button". I'm quite new to these tools - what am I missing?
The Problem is that the tooltips and tipify do not support HTML. That is the reason why your tooltips display the raw HTML created by shiny.18n.
There are two ways to achieve what you want.
The first one is to use popovers from the shinyBS packages. These support HTML and will achieve the language feature you are looking for.
The other one is to render the tooltips on the serverside in shiny. This way no HTML will be involved in creating the translations. This way would allow you to even use tipify/tooltips you asked for.
The reason for this problem is, that shiny.18n has two kind of tricks to achieve the translations. The first one is one the browser side. As you displayed shiny.18n is wrapping a span tag around the translations, so that it can later be modified by using JavaScripts in the browser.
The other method is to render everything new on the server side. This way no HTML will be needed, as the process is happening not on the browser anyway.
is there any way to show all of the contents in the mainPanel only when the user clicks the action button? ive been searching the internet for awhile for the answer but couldn't really find an answer. i know i can use hidden - it works on smaller elements inside the mainPanel, such as showing a picture on click but doesn't work on the whole mainPanel itself. any suggestions? finding a way to wrap the whole main panel inside a hidden instead of each element in the mainPanel wrapped in a hidden would be easier i think but i can't seem to find a way to make it work.
in dashboard body:
fluidRow(
column(12, actionButton("analyze", "Fetch Data!", width = "100px"))),
hidden(
mainPanel(
hidden( (htmlOutput("artistpic")), // this works fine & shows on button click
infoBoxOutput("approvalBox"))
)),
server:
pic <- eventReactive(input$analyze2, {
print(get_id_picture()[3])
url = toString(get_id_picture()[3])
print(url)
url
})
output$artistpic <- renderText({c('<img src="',pic(),'"width="17%" height="17%">')})
This is easy with shinyjs.
Just surround mainPanel() with a div() tag so that you can use it's id for toggling it's visability and start the app with the div tag hidden using hidden() like in the following example:
# ui.R
fluidPage(
useShinyjs(),
actionButton("toggle.main.button", "Toggle Main"),
div(id = "main",
mainPanel(
p("This paragraph is in main."),
p("This one too!")
)
) %>% shinyjs::hidden()
)
# server.R
library(shinyjs)
function(input, output, session) {
# Toggling visability of main on button click.
observeEvent(input$toggle.main.button, {
shinyjs::toggle("main")
})
}
I am trying to understand how will the below code behave
library(shiny)
ui<-fluidPage(
sliderInput("inpslider","Slider",1,10,5),
uiOutput("radio"),
)
server <- function(input, output) {
output$radio<-renderUI({
x<-input$inpslider
radioGroupButtons(inputId = 'myRadioButton', choices = c("A","B"),status = 'warning',
direction = 'vertical', justified = T)
})
}
The first time the code runs it will add an input slider and grouped radio button.
Question:- Since output$radio block contains the reactive value input$slider it will be executed whenever the slider value is changed, So will shiny add a new set of radio button(on top of previous one) every time output$radio is executed? or will the old set of radio buttons will be flushed out every time and new one is added?
You're creating the element with renderUI each time the slider is invalidated it doesnt matter if you press it or reload it...
I'm trying to add a tabPanel in navbarPage so that when you click on it opens a modal window instead of a new tab. The snippet below is not valid because tabPanel does not have an id parameter.
library(shiny)
library(shinyBS)
shinyUI(fluidPage(
navbarPage("Sample App", id = "main_menu",
tabPanel("Open Modal", id = "moda")),
bsModal("modal1", "Example", "moda", p("This is a modal"))
)
If I edit the generated HTML code from browser, I can make this possible by changing the line
Open Modal
with
Open Modal
on the <li> element.
Any idea how to do this or at least how can I override the generated html from shiny?
One solution is to use Javascript to rewrite the attribute for the tab title. The JS code below finds the tab title link, and rewrites its attributes.
library(shiny)
jsStr <- '$(document).ready(function(){
$("a[data-value=\'OpenModal\']").attr({
"href":"#",
"data-toggle":"modal",
"data-target":"#modal1"
});
})
'
ui <- shinyUI(fluidPage(
tags$head(tags$script(HTML(jsStr))),
navbarPage("title",
tabPanel("OpenModal")
),
bsModal("modal1", "Example", "moda", p("This is a modal"))
))
I have created quite a large app that I now want to extent by introducing tabs. So far I have, as an example:
ui.R
shinyUI(
#OLD CODE
)
server.R
(
#OLD CODE
)
What I would like to do:
ui.R
shinyUI(
tabsetPanel(
"Tabs",
tabPanel("Old Code",value="tb1"),
tabPanel("New Code",value="tb2"),
id = "nlp"
),
if (id=="tb1") {
#OLD CODE
} else if (id=="tb2") {
#New Code
} else {
#Do nothing
}
How do I get the if function to recognise id as a variable?
When I run the script it comes up with the error object 'id' not found. So then I've tried input$id and output$id with no avail.
I have also tried going to the server.R and tried
Server.R
output$id <- renderText("id")
also didn't work when trying to bring that back into the UI
and I have also tried
Server.R
output$id <- reactive({input$id})
this also didn't work when I tried to use it in the UI. Where am I going wrong and how can I use the Id variable in the UI?
Thanks
Based on the Shiny Tabsets example, you should be putting the UI elements into each call to tabPanel, like so:
shinyUI(
tabsetPanel(
tabPanel(
title = "Old Code",
plotOutput('plot1'),
plotOutput('plot2')
),
tabPanel(
title = "New Code",
tableOutput('table')
),
id = "nlp"
)
)
Unless you are trying to do more than necessary, your code does not need to know what tab the client has selected. I may be wrong (please do not think I'm an authority on shiny), I think the elements within the not-selected tabs are not unnecessarily recalculated (unless dependencies exist and require it).