Update app configuration and theme at runtime
Sometimes, you want to update the configuration of your app at runtime. Think about changing the global configuration for one or multiple components or updating the theme of your app.
In shinyMobile, there are two functions that can update (parts of) your app:
-
updateF7App()
: injecting any configuration inside the current running instance, includingtheme
,dark
, andcolor.
-
updateF7Entity()
: update a subset of Framework7 instances from the server.
Updating theme, dark mode and color
In essence, updateF7App()
is a pretty simple function:
it takes a list of options and passes it to the running app
instance.
updateF7App(
options = list(
theme = "md",
dark = TRUE,
color = "#007aff"
# any other options
# ...
)
)
The following example shows how to update the theme, dark mode, and color theme of the app:
library(shiny)
library(shinyMobile)
colors <- c(
lightblue = "#5ac8fa",
pink = "#ff2d55",
teal = "#009688",
yellow = "#ffcc00"
)
shinyApp(
ui = f7Page(
title = "Update App",
options = (
list(
color = "#5ac8fa"
)
),
f7SingleLayout(
navbar = f7Navbar(title = "Update App"),
f7BlockTitle("Update theme"),
f7Segment(
f7Button(
inputId = "theme_ios",
"iOS theme"
),
f7Button(
inputId = "theme_md",
"MD theme"
)
),
f7BlockTitle("Set dark mode"),
f7Segment(
f7Button(
inputId = "enable_darkmode",
"Enable darkmode"
),
f7Button(
inputId = "disable_darkmode",
"Disable darkmode"
)
),
f7BlockTitle("Change color theme"),
f7Segment(
tagList(
lapply(names(colors),
function(color) {
f7Button(
inputId = paste0("color_", color),
label = color,
color = color,
)
}
)
)
)
)
),
server = function(input, output, session) {
observeEvent(input$theme_ios, {
updateF7App(
options = list(
theme = "ios"
)
)
})
observeEvent(input$theme_md, {
updateF7App(
options = list(
theme = "md"
)
)
})
observeEvent(input$enable_darkmode, {
updateF7App(
options = list(
dark = TRUE
)
)
})
observeEvent(input$disable_darkmode, {
updateF7App(
options = list(
dark = FALSE
)
)
})
lapply(names(colors), function(color) {
observeEvent(input[[paste0("color_", color)]], {
updateF7App(
options = list(
color = colors[color]
)
)
})
})
}
)
Note that the color can both be a color of getF7Colors()
(like “primary”, “pink” or “teal”) or a hexadecimal color representing
those colors. You can call updateF7App
multiple times, and
the app will update the given configuration settings accordingly.
Updating component configuration
Besides updating the theme, dark mode, and color, you can also update
the configuration of a specific type of component. For example, you can
update the configuration of all the f7Dialog()
components
in an app:
updateF7App(
options = list(
dialog = list(
buttonOk = "Yeaaaah!",
buttonCancel = "Ouuups!"
)
)
)
Above code will update the text shown in the dialog buttons. In the
below app, there are three f7Dialog()
s that will be updated
when the “Update config” button is clicked:
library(shiny)
library(shinyMobile)
shinyApp(
ui = f7Page(
title = "Update App",
f7SingleLayout(
navbar = f7Navbar(title = "Update App"),
f7BlockTitle("Update f7Dialog configuration"),
f7Segment(
f7Button(
inputId = "goButton",
"Show f7Dialog 1"
),
f7Button(
inputId = "goButton2",
"Show f7Dialog 2"
),
f7Button(
inputId = "update",
"Update config"
)
),
)
),
server = function(input, output, session) {
observeEvent(input$goButton, {
f7Dialog(
id = "dialog1",
title = "Dialog title",
text = "This is a confirm dialog",
type = "confirm"
)
})
observeEvent(input$goButton2, {
f7Dialog(
title = "Another dialog title",
text = "This is an alert"
)
})
observeEvent(input$update, {
updateF7App(
options = list(
dialog = list(
buttonOk = "Yeaaaah!",
buttonCancel = "Ouuups!"
)
)
)
f7Dialog(
id = "dialog2",
title = "Warning",
type = "confirm",
text = "Look at me, I have a new buttons!"
)
})
}
)
There are many more components that can be updated in this way. For example:
-
f7Card()
: update the card configuration -
f7Dialog()
: update the dialog configuration, like in the examples above -
f7Panel()
: update (part of) the panel configuration -
f7PhotoBrowser()
: update (part of) the photo browser configuration -
f7Swipeout()
: update the swipeout configuration -
f7Toolbar()
: update the toolbar configuration
Basically, whenever a component in the Framework7 documentation contains
a section on “global app parameters”, you can update these parameters
using updateF7App
.
Update individual components at runtime
If you’re not looking to update the entire app or a particular group
of components, but rather a specific component, you can use
updateF7Entity
. This function allows you to update a subset
of Framework7 instances from the server:
updateF7Entity(
id = "idtoupdate",
options = list(
# your configuration here
)
)
All components that can be updated in this way are:
f7ActionSheet()
f7Gauge()
f7ListIndex()
-
f7PhotoBrowser
() f7Popup()
f7Searchbar()
f7Swiper()
There are still specific update functions for some of the above
components (like updateF7ActionSheet()
and
updateF7Gauge()
), but the aim of
updateF7Entity()
is to provide a more general way to update
them without calling their specific update function.
Below are some examples of how to use
updateF7Entity()
.
Action Sheet
You could update (or reset) the content of an
f7ActionSheet()
like so:
library(shiny)
library(shinyMobile)
shinyApp(
ui = f7Page(
title = "Update Entity",
f7SingleLayout(
navbar = f7Navbar(title = "Update action sheet instance"),
f7Segment(
f7Button(
inputId = "goButton",
label = "Go!"
),
f7Button(
inputId = "update",
label = "Update config"
),
f7Button(
inputId = "reset",
label = "Reset"
)
)
)
),
server = function(input, output, session) {
observeEvent(input$goButton, {
f7ActionSheet(
grid = TRUE,
id = "action1",
buttons = list(
list(
text = "Notification",
icon = f7Icon("info"),
color = NULL
),
list(
text = "Dialog",
icon = f7Icon("lightbulb_fill"),
color = NULL
)
)
)
})
observeEvent(input$update, {
updateF7Entity(
id = "action1",
options = list(
buttons = list(
list(
text = "Notification",
icon = f7Icon("info"),
color = NULL
)
)
)
)
})
observeEvent(input$reset, {
updateF7Entity(
id = "action1",
options = list(
buttons = list(
list(
text = "Notification",
icon = f7Icon("info"),
color = NULL
),
list(
text = "Dialog",
icon = f7Icon("lightbulb_fill"),
color = NULL
)
)
)
)
})
}
)
In the above example, we update the content of buttons
in the f7ActionSheet()
with the id action1
.
This way, you can update the component at runtime.
A similar result can be achieved with
updateF7ActionSheet()
.
Gauge
Changing the value of a gauge is a common task and perfectly possible
with updateF7Entity()
:
library(shiny)
library(shinyMobile)
shinyApp(
ui = f7Page(
title = "Gauges",
f7SingleLayout(
navbar = f7Navbar(title = "f7Gauge"),
f7Segment(
f7Button(
inputId = "update",
label = "Update Gauge"
),
f7Button(
inputId = "reset",
label = "Reset"
)
),
f7Block(
f7Gauge(
id = "mygauge",
type = "semicircle",
value = 50,
borderColor = "#2196f3",
borderWidth = 10,
valueFontSize = 41,
valueTextColor = "#2196f3",
labelText = "amount of something"
)
)
)
),
server = function(input, output, session) {
observeEvent(input$update, {
new_val <- 75
updateF7Entity(
id = "mygauge",
options = list(
# Must be between 0 and 1
value = new_val / 100,
valueText = paste0(new_val, "%"),
labelText = "New label!"
)
)
})
observeEvent(input$reset, {
updateF7Entity(
id = "mygauge",
options = list(
value = 50 / 100,
valueText = "50%",
labelText = "amount of something"
)
)
})
}
)
A similar result can be achieved with the
updateF7Gauge()
.
List Index
The f7ListIndex()
component has limited configuration
options. Most of the default options make the most sense for this
particular component. But, you could update the label (bubble with
selected index when you swipe over list index) of a
f7ListIndex()
component like so:
library(shiny)
library(shinyMobile)
shinyApp(
ui = f7Page(
title = "My app",
f7SingleLayout(
navbar = f7Navbar(title = "f7List"),
f7Segment(
f7Button(
inputId = "update",
label = "Update"
),
f7Button(
inputId = "reset",
label = "Reset"
)
),
f7List(
id = "mycontacts",
mode = "contacts",
lapply(1:3, function(i) {
f7ListGroup(
title = LETTERS[i],
lapply(1:10, function(j) f7ListItem(letters[j]))
)
})
)
)
),
server = function(input, output, session) {
f7ListIndex(id = "contacts",
target = "#mycontacts",
label = TRUE)
observeEvent(input$update, {
updateF7Entity(
"contacts",
options = list(
label = FALSE
)
)
})
observeEvent(input$reset, {
updateF7Entity(
"contacts",
options = list(
label = TRUE
)
)
})
}
)
Photo Browser
Using updateF7Entity()
, you can update the photos that
are displayed in the photo browser and any other configuration:
library(shiny)
library(shinyMobile)
shinyApp(
ui = f7Page(
title = "f7PhotoBrowser",
f7SingleLayout(
navbar = f7Navbar(title = "f7PhotoBrowser"),
f7Segment(
f7Button(
inputId = "togglePhoto",
label = "Open photo"
),
f7Button(
inputId = "update",
label = "Update"
)
)
)
),
server = function(input, output, session) {
observeEvent(input$togglePhoto, {
f7PhotoBrowser(
id = "photobrowser1",
theme = "dark",
type = "page",
photos = list(
list(url = "https://cdn.framework7.io/placeholder/sports-1024x1024-1.jpg"),
list(url = "https://cdn.framework7.io/placeholder/sports-1024x1024-2.jpg"),
list(url = "https://cdn.framework7.io/placeholder/sports-1024x1024-3.jpg",
caption = "Me cycling")
),
thumbs = c(
"https://cdn.framework7.io/placeholder/sports-1024x1024-1.jpg",
"https://cdn.framework7.io/placeholder/sports-1024x1024-2.jpg",
"https://cdn.framework7.io/placeholder/sports-1024x1024-3.jpg"
)
)
})
observeEvent(input$update, {
updateF7Entity(
"photobrowser1",
options = list(
type = "popup",
popupPush = TRUE,
toolbar = FALSE,
photos = list(
list(url = "https://cdn.framework7.io/placeholder/sports-1024x1024-1.jpg")
),
thumbs = list("https://cdn.framework7.io/placeholder/sports-1024x1024-1.jpg")
)
)
})
}
)
Popup
For the f7Popup()
component, you will need a bit more
code to make updates. Within updateF7Entity()
, you need to
provide the necessary HTML of the popup content:
library(shiny)
library(shinyMobile)
shinyApp(
ui = f7Page(
title = "Popup",
f7SingleLayout(
navbar = f7Navbar(
title = "f7Popup"
),
f7Segment(
f7Button(
inputId = "toggle",
label = "Toggle Popup"
),
f7Button(
inputId = "update",
label = "Update Popup")
)
)
),
server = function(input, output, session) {
output$res <- renderPrint(input$text)
observeEvent(input$toggle, {
f7Popup(
id = "popup",
title = "My first popup",
f7Text(
"text", "Popup content",
"This is my first popup ever, I swear!"
),
verbatimTextOutput("res")
)
})
observeEvent(input$update, {
updateF7Entity(
id = "popup",
options = list(
swipeToClose = TRUE,
animate = FALSE,
closeOnEscape = TRUE,
# Content must contain the popup
# layout!!!
content = '<div class="popup">
<div class="view">
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
<div class="title">Popup</div>
<div class="right">
<!-- Link to close popup -->
<a class="link popup-close">Close</a>
</div>
</div>
</div>
<div class="page-content">
<div class="block">New content ...</div>
</div>
</div>
</div>
</div>'
)
)
})
}
)
Searchbar
In a Searchbar, you can have a disable button: a “Cancel” (or “Back”)
button that will deactivate the Searchbar, reset search results and
clear search field. In below example this button is excluded with
options(list(disableButton = FALSE))
when update is being
clicked:
library(shiny)
library(shinyMobile)
cities <- names(precip)
shinyApp(
ui = f7Page(
title = "Expandable searchbar",
f7SingleLayout(
navbar = f7Navbar(
title = "f7Searchbar with trigger",
subNavbar = f7SubNavbar(
f7Searchbar(
id = "search1",
expandable = TRUE
)
)
),
f7Segment(
f7Button(
inputId = "update",
label = "Update"
),
f7Button(
inputId = "reset",
label = "Reset"
)
),
f7Block(
f7SearchbarTrigger(targetId = "search1")
) %>% f7HideOnSearch(),
f7List(
lapply(seq_along(cities), function(i) {
f7ListItem(cities[i])
})
) %>% f7Found(),
f7Block(
p("Nothing found")
) %>% f7NotFound()
)
),
server = function(input, output) {
observeEvent(input$update, {
updateF7Entity(
id = "search1",
options = list(
disableButton = FALSE
)
)
})
observeEvent(input$reset, {
updateF7Entity(
id = "search1",
options = list(
disableButton = TRUE
)
)
})
}
)
Swiper
There are many options to customize the f7Swiper()
component. Note that on desktop you need to click and hold to swipe:
library(shiny)
library(shinyMobile)
shinyApp(
ui = f7Page(
title = "Swiper",
f7SingleLayout(
navbar = f7Navbar(title = "f7Swiper"),
f7Segment(
f7Button(
inputId = "update",
label = "Update"
),
f7Button(
inputId = "reset",
label = "Reset"
)
),
f7Swiper(
id = "swiper",
options = list(
navigation = list(
enabled = FALSE
),
pagination = list(
enabled = TRUE,
el = ".swiper-pagination",
clickable = TRUE
)
),
lapply(1:20, function(c) {
f7Slide(
f7Card(
title = sprintf("Slide %s", c)
)
)
})
)
)
),
server = function(input, output) {
observeEvent(input$update, {
updateF7Entity(
"swiper",
options = list(
speed = 100,
slidesPerView = 2,
spaceBetween = 10,
autoplay = TRUE,
scrollbar = list(
enabled = FALSE
),
pagination = list(
type = "progressbar",
enabled = TRUE
),
grid = list(
fill = "columns",
rows = 4
)
)
)
})
observeEvent(input$reset, {
updateF7Entity(
"swiper",
options = list(
speed = 400,
slidesPerView = "auto",
spaceBetween = 50,
autoplay = FALSE,
scrollbar = list(
enabled = TRUE
),
pagination = list(
type = "bullets",
enabled = TRUE
),
grid = list(
fill = "column",
rows = 1
)
)
)
})
}
)