diff --git a/pkg-r/R/QueryChat.R b/pkg-r/R/QueryChat.R index fe4a2f9f..863e4bd1 100644 --- a/pkg-r/R/QueryChat.R +++ b/pkg-r/R/QueryChat.R @@ -474,8 +474,10 @@ QueryChat <- R6::R6Class( #' @param width Width of the sidebar in pixels. Default is 400. #' @param height Height of the sidebar. Default is "100%". #' @param fillable Whether the sidebar should be fillable. Default is `TRUE`. - #' @param ns A Shiny namespacing (i.e., [shiny::NS()]) function. - #' Only needed when calling this method within a module UI function. + #' @param id Optional ID for the QueryChat instance. If not provided, + #' will use the ID provided at initialization. If using `$sidebar()` in + #' a Shiny module, you'll need to provide `id = ns("your_id")` where `ns` + #' is the namespacing function from [shiny::NS()]. #' #' @return A [bslib::sidebar()] UI component. #' @@ -493,7 +495,7 @@ QueryChat <- R6::R6Class( width = 400, height = "100%", fillable = TRUE, - ns = NULL + id = NULL ) { bslib::sidebar( width = width, @@ -501,7 +503,7 @@ QueryChat <- R6::R6Class( fillable = fillable, class = "querychat-sidebar", ..., - self$ui(ns = ns) + self$ui(id = id) ) }, @@ -512,8 +514,10 @@ QueryChat <- R6::R6Class( #' `$sidebar()` instead, which wraps this in a sidebar layout. #' #' @param ... Additional arguments passed to [shinychat::chat_ui()]. - #' @param ns A Shiny namespacing (i.e., [shiny::NS()]) function. - #' Only needed when calling this method within a module UI function. + #' @param id Optional ID for the QueryChat instance. If not provided, + #' will use the ID provided at initialization. If using `$ui()` in a Shiny + #' module, you'll need to provide `id = ns("your_id")` where `ns` is the + #' namespacing function from [shiny::NS()]. #' #' @return A UI component containing the chat interface. #' @@ -525,27 +529,16 @@ QueryChat <- R6::R6Class( #' qc$ui() #' ) #' } - ui = function(..., ns = NULL) { - check_function(ns, allow_null = TRUE) + ui = function(..., id = NULL) { + check_string(id, allow_null = TRUE, allow_empty = FALSE) # If called within another module, the UI id needs to be namespaced # by that "parent" module. If called in a module *server* context, we # can infer the namespace from the session, but if not, the user # will need to provide it. - # NOTE: this isn't a problem for Python since id namespacing is handled implicitly - # by UI functions like shinychat.chat_ui(). - id <- self$id - id <- if (is.null(ns)) namespaced_id(id) else ns(id) - - # Provide a helpful error if the user tries to set id directly - if ("id" %in% names(list2(...))) { - cli::cli_abort( - c( - "Not allowed to set {.arg id} to {.fn $ui()} (or {.fn $sidebar()}).", - "i" = "Use the {.arg ns} argument instead to namespace the UI id." - ) - ) - } + # NOTE: this isn't a problem for Python since id namespacing is handled + # implicitly by UI functions like shinychat.chat_ui(). + id <- id %||% namespaced_id(self$id) mod_ui(id, ...) }, @@ -563,6 +556,12 @@ QueryChat <- R6::R6Class( #' with Shiny bookmarks. This requires that the Shiny app has bookmarking #' enabled via `shiny::enableBookmarking()` or the `enableBookmarking` #' parameter of `shiny::shinyApp()`. + #' @param ... Ignored. + #' @param id Optional module ID for the QueryChat instance. If not provided, + #' will use the ID provided at initialization. When used in Shiny modules, + #' this `id` should match the `id` used in the corresponding UI function + #' (i.e., `qc$ui(id = ns("your_id"))` pairs with `qc$server(id = + #' "your_id")`). #' @param session The Shiny session object. #' #' @return A list containing session-specific reactive values and the chat @@ -586,8 +585,13 @@ QueryChat <- R6::R6Class( #' } server = function( enable_bookmarking = FALSE, + ..., + id = NULL, session = shiny::getDefaultReactiveDomain() ) { + check_string(id, allow_null = TRUE, allow_empty = FALSE) + check_dots_empty() + if (is.null(session)) { cli::cli_abort( "{.fn $server} must be called within a Shiny server function" @@ -595,7 +599,7 @@ QueryChat <- R6::R6Class( } mod_server( - self$id, + id %||% self$id, data_source = private$.data_source, greeting = self$greeting, client = self$client, diff --git a/pkg-r/man/QueryChat.Rd b/pkg-r/man/QueryChat.Rd index 083e214f..64f15b0a 100644 --- a/pkg-r/man/QueryChat.Rd +++ b/pkg-r/man/QueryChat.Rd @@ -489,7 +489,7 @@ interface, suitable for use with \code{\link[bslib:page_sidebar]{bslib::page_sid width = 400, height = "100\%", fillable = TRUE, - ns = NULL + id = NULL )}\if{html}{\out{}} } @@ -504,8 +504,10 @@ interface, suitable for use with \code{\link[bslib:page_sidebar]{bslib::page_sid \item{\code{fillable}}{Whether the sidebar should be fillable. Default is \code{TRUE}.} -\item{\code{ns}}{A Shiny namespacing (i.e., \code{\link[shiny:NS]{shiny::NS()}}) function. -Only needed when calling this method within a module UI function.} +\item{\code{id}}{Optional ID for the QueryChat instance. If not provided, +will use the ID provided at initialization. If using \verb{$sidebar()} in +a Shiny module, you'll need to provide \code{id = ns("your_id")} where \code{ns} +is the namespacing function from \code{\link[shiny:NS]{shiny::NS()}}.} } \if{html}{\out{}} } @@ -537,7 +539,7 @@ Create the UI for the querychat chat interface. This method generates the chat UI component. Typically you'll use \verb{$sidebar()} instead, which wraps this in a sidebar layout. \subsection{Usage}{ -\if{html}{\out{