Search code examples
rshinyshinydashboardshinydashboardplusslickr

How can I render a Carousel in R Shiny that has image and text with SlickR?


I'm working on a Shiny app to develop a test environment for a recommender system in the backend and I want to render some carousels to show the results of the recommender algorithms. I'm using a library called 'SlickR' that is very easy to use and the visual is pretty good, but i'm having some problems to render a carousel with text and image in shiny.

The thing is that when I render the carousel as I need it in a normal R Script, everything works fine, with the image and the text on the bottom and the horizontal scrolling working fine, just like this:

enter image description here

And this is the code:

library(slickR)

x <- slickR(obj = c("img_1","img_2","img_3","img_4","img_5","img_6","img_7","img_8"),
            slideType = 'p',
            height = 100) +
  settings(dots = TRUE,arrows = FALSE,slidesToShow = 3,slidesToScroll = 3)
y <- slickR(obj = sample(list.files(here::here("www/categories/"),
                                    full.names = TRUE)),
            height = 100) + 
  settings(dots = FALSE,slidesToShow = 3,slidesToScroll = 3)

y %synch% x

Pretty simple and everything looks good, but the thing is than when I wrap exactly the same code in a 'renderSlickR' object like this

      output$slick_output_1 <- renderSlickR({
    
    x <- slickR(obj = c("img_1","img_2","img_3","img_4","img_5","img_6","img_7","img_8"),slideType = 'p',height = 100) + 
      settings(dots = TRUE,arrows = FALSE,slidesToShow = 3,slidesToScroll = 3)
    y <- slickR(obj = sample(list.files(here::here("www/categories/"),full.names = TRUE)),height = 100) + 
      settings(dots = FALSE,slidesToShow = 3,slidesToScroll = 3)
      
    y %synch% x 
})

And send it to the ui with box(slickROutput("slick_output_1"),title = "Reel 1",width = 12) this happens:

enter image description here

The images don't show anymore and just the text render, but also, the carousel gets stuck and don't scroll to the left/right, the arrows at the sides do not render aswell.

The only option that worked for me in shiny is if I set the dots parameter to TRUE in the settings for both objects like this:

  output$slick_output_1 <- renderSlickR({
    
    #This works fine because dots is TRUE in the settings for both objects
    #but this code don't render the expected output
    
    x <- slickR(obj = c("img_1","img_2","img_3","img_4","img_5","img_6","img_7","img_8"),slideType = 'p',height = 100) +
      settings(dots = TRUE,arrows = FALSE,slidesToShow = 3,slidesToScroll = 3)
    y <- slickR(obj = sample(list.files(here::here("www/categories/"),full.names = TRUE)),height = 100) + 
      settings(dots = TRUE,slidesToShow = 3,slidesToScroll = 3)
      
    y %synch% x
  })

But the output is not the expected because it render the 2 carousel synched (one with the images and one with the text) but both with the (...) at the bottom to change the slides:

enter image description here

Any other combination of the dots parameter will result on a freeze of the carousel and in a unexpected outcome in shiny, the strange thing is that if the dots parameter remains TRUE, it will work, but it's not what we want, but if I run it in a normal R script, any combination work and all the outcomes render the carousels correctly.

For me it looks like a bug of the library when it is used with shiny, but i wanted to ask the community if someone had the same issue before, if we agree that it's a bug, or if i'm doing something wrong, or even if someone knows an alternative.

Any comments are welcome! Thanks!


Solution

  • I think the cause is the following one. The slickR function returns a HTML element with an id, and by default this id is baseDiv. So with your code you get two HTML elements having the same id, and this is not allowed in a HTML document. Therefore, if you provide two different id, with the slideId argument, that should work.

    library(shiny)
    library(slickR)
    
    ui <- fluidPage(
      br(),
      slickROutput("s")
    )
    
    server <- function(input, output) {
      output$s <- renderSlickR({
        x <- slickR(obj = nba_player_logo$uri[1:3], slideId = "slick1")
        y <- slickR(obj = c("img1", "img2", "img3"), slideType = "p", slideId = "slick2")
        y %synch% x
      })
    }
    
    shinyApp(ui, server)