Skip to content

Commit 1744be8

Browse files
committed
fix(pkg-r): better support for modules. Closes #169
1 parent 93dcaf8 commit 1744be8

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed

pkg-r/R/QueryChat.R

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ QueryChat <- R6::R6Class(
7272
public = list(
7373
#' @field greeting The greeting message displayed to users.
7474
greeting = NULL,
75-
#' @field id The module ID for namespacing.
75+
#' @field id ID for the QueryChat instance.
7676
id = NULL,
7777

7878
#' @description
@@ -378,10 +378,12 @@ QueryChat <- R6::R6Class(
378378
#' This method generates a [bslib::sidebar()] component containing the chat
379379
#' interface, suitable for use with [bslib::page_sidebar()] or similar layouts.
380380
#'
381+
#' @param ... Additional arguments passed to [bslib::sidebar()].
381382
#' @param width Width of the sidebar in pixels. Default is 400.
382383
#' @param height Height of the sidebar. Default is "100%".
383384
#' @param fillable Whether the sidebar should be fillable. Default is `TRUE`.
384-
#' @param ... Additional arguments passed to [bslib::sidebar()].
385+
#' @param ns A Shiny namespacing (i.e., [shiny::NS()]) function.
386+
#' Only needed when calling this method within a module UI function.
385387
#'
386388
#' @return A [bslib::sidebar()] UI component.
387389
#'
@@ -394,14 +396,20 @@ QueryChat <- R6::R6Class(
394396
#' # Main content here
395397
#' )
396398
#' }
397-
sidebar = function(width = 400, height = "100%", fillable = TRUE, ...) {
399+
sidebar = function(
400+
...,
401+
width = 400,
402+
height = "100%",
403+
fillable = TRUE,
404+
ns = NULL
405+
) {
398406
bslib::sidebar(
399407
width = width,
400408
height = height,
401409
fillable = fillable,
402410
class = "querychat-sidebar",
403411
...,
404-
self$ui()
412+
self$ui(ns = ns)
405413
)
406414
},
407415

@@ -412,6 +420,8 @@ QueryChat <- R6::R6Class(
412420
#' `$sidebar()` instead, which wraps this in a sidebar layout.
413421
#'
414422
#' @param ... Additional arguments passed to [shinychat::chat_ui()].
423+
#' @param ns A Shiny namespacing (i.e., [shiny::NS()]) function.
424+
#' Only needed when calling this method within a module UI function.
415425
#'
416426
#' @return A UI component containing the chat interface.
417427
#'
@@ -423,8 +433,29 @@ QueryChat <- R6::R6Class(
423433
#' qc$ui()
424434
#' )
425435
#' }
426-
ui = function(...) {
427-
mod_ui(self$id, ...)
436+
ui = function(..., ns = NULL) {
437+
check_function(ns, allow_null = TRUE)
438+
439+
# If called within another module, the UI id needs to be namespaced
440+
# by that "parent" module. If called in a module *server* context, we
441+
# can infer the namespace from the session, but if not, the user
442+
# will need to provide it.
443+
# NOTE: this isn't a problem for Python since id namespacing is handled implicitly
444+
# by UI functions like shinychat.chat_ui().
445+
id <- self$id
446+
id <- if (is.null(ns)) namespaced_id(id) else ns(id)
447+
448+
# Provide a helpful error if the user tries to set id directly
449+
if ("id" %in% names(list2(...))) {
450+
cli::cli_abort(
451+
c(
452+
"Not allowed to set {.arg id} to {.fn $ui()} (or {.fn $sidebar()}).",
453+
"i" = "Use the {.arg ns} argument instead to namespace the UI id."
454+
)
455+
)
456+
}
457+
458+
mod_ui(id, ...)
428459
},
429460

430461
#' @description
@@ -724,3 +755,12 @@ normalize_data_source <- function(data_source, table_name) {
724755
"{.arg data_source} must be a {.cls DataSource}, {.cls data.frame}, or {.cls DBIConnection}, not {.obj_type_friendly {data_source}}."
725756
)
726757
}
758+
759+
760+
namespaced_id <- function(id, session = shiny::getDefaultReactiveDomain()) {
761+
if (is.null(session)) {
762+
id
763+
} else {
764+
session$ns(id)
765+
}
766+
}

pkg-r/man/QueryChat.Rd

Lines changed: 16 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)