A scrolling area that asks the server for more as the user nears the bottom. Element implements this as a directive rather than a component, so the area is a container you put content into.
Usage
el_infinite_scroll(
id = NULL,
...,
height = "300px",
disabled = NULL,
delay = NULL,
distance = NULL,
immediate = NULL,
width = NULL,
slots = NULL,
session = NULL
)
update_el_infinite_scroll(
session = shiny::getDefaultReactiveDomain(),
id,
disabled = NULL,
delay = NULL,
distance = NULL
)Arguments
- id
Container ID. Auto-generated if
NULL.- ...
Content of the scrolling area. Any Shiny UI, including shiny.element components – those are folded into this container's Vue instance rather than nested inside it, so their inputs keep reporting. Their
update_el_*()no longer reaches them, though.- height
Height of the area, as a CSS unit. Needed for it to scroll at all. Default
"300px".- disabled
Whether loading is suspended. Set it from the server while a request is in flight, and again when there is nothing left to fetch.
- delay
Throttle between checks, in milliseconds. Default
200.- distance
How near the bottom to get before asking, in pixels. Default
0.- immediate
Whether to ask once on load, in case the content does not fill the area. Default
TRUE.- width
Component width, as a CSS unit.
- slots
Named list of Element slot contents, such as
list(title = shiny::tags$b("Bold")). A shiny.element component given here is absorbed rather than nested. For a scoped slot, write the template withtemplate().- session
In
el_infinite_scroll(), deprecated: inside a module, wrapidinns(), as for any Shiny input; a session given here namespacesidonce more, with a warning. Inupdate_el_infinite_scroll(), the Shiny session, the current one by default, as forshiny::updateTextInput().
Shiny inputs
input$<id>_load– rises by one each time more content is wanted. Observe it, fetch the next page, and render it into ashiny::uiOutput()inside the area.
Updating from the server
Server-side update for el_infinite_scroll(). Setting disabled is how a
feed stops asking once everything has been sent.
update_el_infinite_scroll() is called for its side effect and returns NULL invisibly.
Examples
el_infinite_scroll("feed", shiny::uiOutput("rows"), height = "400px")
#> <div id="feed" data-shiny-vue style="display: contents">
#> <script type="text/x-template" data-shiny-vue-template><div id="feed_container" style="display: contents">
#> <div v-infinite-scroll="handleLoad" :infinite-scroll-disabled="scrollDisabled" :infinite-scroll-delay="scrollDelay === null ? undefined : scrollDelay" :infinite-scroll-distance="scrollDistance === null ? undefined : scrollDistance" :infinite-scroll-immediate="scrollImmediate === null ? undefined : scrollImmediate" style="overflow: auto; height: 400px">
#> <div id="rows" class="shiny-html-output"></div>
#> </div>
#> </div></script>
#> <script type="application/json" data-shiny-vue-options>{"options":{"data":{"scrollDisabled":false,"scrollDelay":null,"scrollDistance":null,"scrollImmediate":null,"scrollCount":0},"methods":{"handleLoad":"function() { this.scrollCount++; window.Shiny && Shiny.setInputValue && Shiny.setInputValue('feed_load', this.scrollCount); }"}},"input":null,"rate":null,"type":null,"use":["shinyElement.plugin"],"evals":["options.methods.handleLoad"]}</script>
#> </div>
if (interactive()) {
library(shiny)
library(shiny.element)
ui <- el_page(el_infinite_scroll("feed", uiOutput("rows")))
server <- function(input, output, session) {
shown <- reactiveVal(20)
observeEvent(input$feed_load, {
shown(min(shown() + 20, nrow(iris)))
})
output$rows <- renderUI({
lapply(seq_len(shown()), function(i) tags$p(paste("Row", i)))
})
}
shinyApp(ui, server)
}
if (interactive()) {
# inside a server function
observeEvent(input$feed_load, {
if (all_rows_sent()) {
update_el_infinite_scroll(session, "feed", disabled = TRUE)
}
})
}