dfe-analytical-services / dfeshiny

R package containing preferred methods for creating official DfE R Shiny dashboards
https://dfe-analytical-services.github.io/dfeshiny/
GNU General Public License v3.0
4 stars 1 forks source link

Internal link function #51

Open JT-39 opened 3 weeks ago

JT-39 commented 3 weeks ago

Is your feature request related to a problem? Please describe.

With inspiration from dfeshiny::external_link(), what about `dfeshiny::internal_link()?

I want to be able to link to another page (or tab) from within my Shiny app.

Describe the solution you'd like

A simple function/ module to be able to link from one tab to another in a Shiny app.

Describe alternatives you've considered

You need to add an observeEvent() function to the server.R script for any link that navigates within your App.

Additional context

Module to do this (in bslib):

# Internal link UI function
InternalLinkUI <- function(id) {
  ns <- shiny::NS(id) # Namespace the module
  actionLink(ns("internal_link"), "LA Level page")
}

# Internal link server function
InternalLinkServer <- function(id,
                               tabset_id,
                               tab_value,
                               parent_session) {
  moduleServer(id, function(input, output, session) {
    observeEvent(input$internal_link, {
      # Switch to the specified tab
      bslib::nav_select(
        id = tabset_id,
        selected = tab_value,
        session = parent_session
      )
    })
  })
}
cjrace commented 3 weeks ago

I guess this might be quite specific to how you've set your app up, though given the general push (even from POSIT) towards bslib, we could look at adding this use case for bslib tabs in specifically in as a specific helper that saves a little bit a of code for analysts, agree on having it as a module pair, should be a fairly quick addition to the package 😄

I think the server function would only need id and tabset_id as arguments and you could reuse that main id as the id for tab_value, the ui function would then have id, tabset_id and link_text as arguments? For the link text argument we could add some basic validation to make sure it's not too short or on the 'naughty list' we've got for external_link.

Could also add an example or two for where you have multiple pages you link to, and can then in the server use something like lapply to create all the server modules in a super efficient way.

JT-39 commented 1 week ago

Definitely, its quite a niche usage but does push people to using {bslib} which I think is best practice in Shiny apps now.

Oooo, I like the use of id for the tab_value, I had never even thought of using the id of a module for something within it, this has opened a whole new door of possibilities! (Or at least not just wasted id parameter lol!)

I am a bit confused, why would we not need the parent_session parameter?

Yep, really like that example - and shows off lapply() too!

cjrace commented 1 week ago

Yeah, anything pushing towards bslib is probably a good thing, and ID params in modules can be very nifty! Well worth making use of them to streamline the code.

For the parent_session I'm not 100% sure, though my assumption was it might always be availavle from a global context so doesn't need explicitly passing into the module. Would need to check it when implementing.

One other thing I think whoever implements this should consider (even if it's future me, writing here so I don't forget!) - is how it'll handle ID clashes, for example if you wanted to link to a given tab from multiple places in the app, how would that work, and what would be best practice. Ideally you'd only need one server call, but I don't know how that'd work in practice without playing about with it.