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, including theme
,
dark
, and color.
updateF7Entity()
: update a subset of Framework7
instances from the server.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.
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:
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
configurationf7Dialog()
: update the dialog
configuration, like in the examples abovef7Panel()
: update (part of) the panel
configurationf7PhotoBrowser()
: update (part of) the photo
browser configurationf7Swipeout()
: update the swipeout
configurationf7Toolbar()
: update the toolbar
configurationBasically, whenever a component in the Framework7 documentation contains
a section on “global app parameters”, you can update these parameters
using updateF7App
.
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:
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()
.
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()
.
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()
.
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
)
)
})
}
)
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")
)
)
})
}
)
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>'
)
)
})
}
)
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
)
)
})
}
)
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, \(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
)
)
)
})
}
)