JohnCoene / cicerone

🏛️ Give tours of your Shiny apps
https://cicerone.john-coene.com
Other
187 stars 7 forks source link

Multiple guided tour #30

Open ShinyFabio opened 3 years ago

ShinyFabio commented 3 years ago

Hello, I have a very complex shiny app with a lot of tabpanels, conditionapanels, shinydashboards etc. Since a unique guided tour will be impossible and veeeery long, is it possible to make many different guided tours activated by a button? Something like this:

  guided_tour =  cicerone::Cicerone$
    new()$
    step(
      el = "delim",
      title = "Delimitatore",
      description = "Qui scegliere il delimitatore del file."
    )$
    step(
      "header",
      "Enable header",
      "Scegli se è presente l'header."
    )

  # initialise then start the guide
  guided_tour$init()

  observeEvent(input$useguide, {
    guided_tour$start()
  })

  guided_tour2 =  cicerone::Cicerone$
    new()$ 
    step(
      el = "selectx",
      title = "Asse X",
      description = "Qui scegliere l'asse x.",
      tab = 
    )$
    step(
      "selecty",
      "Asse Y",
      "Qui scegliere l'asse Y."
    )

  # initialise then start the guide
  guided_tour2$init()

  observeEvent(input$useguide2, {
    guided_tour2$start()
  })

So as you can see I have two guided_tour with two buttons and they are in different tabs. I tried this code but it didn't work.

JohnCoene commented 3 years ago

We can't have two tours triggered at the same time so I would suggest something like this.

library(shiny)
library(cicerone)

guided_tour <- cicerone::Cicerone$
  new()$
  step(
    el = "delim",
    title = "Delimitatore",
    description = "Qui scegliere il delimitatore del file."
  )$
  step(
    "header",
    "Enable header",
    "Scegli se è presente l'header."
  )

guided_tour2 <- cicerone::Cicerone$
  new()$ 
  step(
    el = "selectx",
    title = "Asse X",
    description = "Qui scegliere l'asse x."
  )

ui <- navbarPage(
  "Cicerone",
  header = list(
    use_cicerone()
  ),
  id = "nav",
  tabPanel(
    "First",
    h1("Delim!", id = "delim")
  ),
  tabPanel(
    "Second",
    h1("Select X", id = "selectx")
  )
)

server <- function(input, output, session){

  guided_tour$init()$start()

  started <- FALSE
  observeEvent(input$nav, {
    if(input$nav == "Second"){
      guided_tour2$init()$start()
      started <<- TRUE
    }
  })  
}

shinyApp(ui, server)

Does that work?

ShinyFabio commented 3 years ago

So, if I am right, the code triggers the first guided_tour and then if I'm in the second navbarpage ("Second") it triggers the second guided_tour2. Since I want the guided tour starts only after pressed a button, I successfully run two cicerones with two different buttons with this modification:


ui <- navbarPage(
  "Cicerone",
  header = list(
    use_cicerone()
  ),
  id = "nav",
  tabPanel(
    "First",
    actionButton(inputId = "button2", "vai guida"),
    h1("Delim!", id = "delim")

  ),
  tabPanel(
    "Second",
    shiny::actionButton(inputId = "button", "vai guida"),
    h1("Select X", id = "selectx")
  )
)

server <- function(input, output, session){

  observeEvent(input$button2, {
      guided_tour$init()$start()
  })

  observeEvent(input$button, {
      guided_tour2$init()$start()
  })  
}

shinyApp(ui, server)

But I didn't understand what 's the function of started. You defined this variable and changed the value from FALSEto TRUEbut I can't figure out how cicerone uses it. My code works also without it.

Also I didn't even understand this line:

header = list(
    use_cicerone()
  ),

What does this code do? Thanks

JohnCoene commented 3 years ago

You can of course use two buttons but I thought you only want one.

The code below does that with a button.

library(shiny)
library(cicerone)

guided_tour <- cicerone::Cicerone$
  new()$
  step(
    el = "delim",
    title = "Delimitatore",
    description = "Qui scegliere il delimitatore del file."
  )

guided_tour2 <- cicerone::Cicerone$
  new()$ 
  step(
    el = "selectx",
    title = "Asse X",
    description = "Qui scegliere l'asse x."
  )

ui <- navbarPage(
  "Cicerone",
  header = list(
    use_cicerone() # import dependencies
  ),
  id = "nav",
  tabPanel(
    "First",
    h1("Delim!", id = "delim"),
    actionButton("start", "Start tour")
  ),
  tabPanel(
    "Second",
    h1("Select X", id = "selectx")
  )
)

server <- function(input, output, session){

  start_tour <- FALSE
  observeEvent(input$start, {
    guided_tour$init()$start()
    start_tour <<- TRUE
  })

  ran_tour2 <- FALSE
  observeEvent(input$nav, {

    # exit early if there is no need to start the tour
    if(!start_tour)
      return()

    # if second tab + tour not ran yet, start the tour
    if(input$nav == "Second" && !ran_tour2){
      guided_tour2$init()$start()
      ran_tour2 <<- TRUE # tour started
    }
  })  
}

shinyApp(ui, server)

Those variables are simply used to check whether the tours should be triggered, otherwise they will be triggered every time someone visits the second tab.

The function use_cicerone is to import the JavaScript and CSS dependencies required to run the code browser-side.

ShinyFabio commented 3 years ago

Ok thanks! So if I want to trigger the tours only when I push a button I don't need those variables , am I right? I need it only if the tour starts automatically like triggered from a tab or maybe a radiobutton() (?). While about the other part of the code, I was confused more about header = list() than the simply use_cicerone(). I tested it without the header but doesn't work, so I imagine I need it.