The generated control widgets (layer picker, per-layer parameter
panels, the "Update plot" button) as a bare shiny::tagList() with
no .ptr-app wrapper and no bundled assets. One of the
single-piece UI builders for the L3 "own every UI piece" workflow:
compose it with ptr_ui_assets() and the output pieces, place each
wherever you like, and wire the server with ptr_server() /
ptr_server().
Usage
ptr_ui_controls(
formula,
id = NULL,
envir = parent.frame(),
ui_text = NULL,
expr_check = TRUE,
shared = NULL
)Arguments
- formula
Either a single character scalar containing a ggplot expression with
ggpaintrplaceholders, or an unquoted /!!-spliced ggplot expression, captured withrlang::enexpr()exactly asptr_app()/ptr_server(). Seeptr_app()for the full contract.- id
Optional module id; the namespace prefix for inputs. Defaults to
NULL(identity namespace). When set, must match theidpassed to the other piece functions and the server wiring.- envir
Environment used to resolve a
formulapassed as a bare symbol and any local data objects. Defaults to the calling frame.- ui_text
Optional named list of copy overrides; see
ptr_ui_text()for the full schema and current defaults.- expr_check
Controls formula-level
ppExprvalidation:TRUE(default) applies the built-in denylist + AST walker;FALSEdisables formula-level validation; alistwithdeny_list/allow_listentries customises the formula-level policy. Runtime-typedppExprinput is always screened against the built-in denylist regardless. See the safety chapter of the ggpaintr book (development-version docs): https://willju-wangqian.github.io/ggpaintr-book/safety.html.Optional coordinator object from
ptr_shared()for the multi-instance embedding. WhenNULL(the single-instance default) the inline "Shared controls" section renders everyshared = "..."placeholder informula. When aptr_shared_specis supplied, its cross-formula keys (shared$panel_keys) are excluded here because they belong to the one standaloneptr_shared_panel(); only this formula's formula-local shared keys render inline.
Details
Because the panel includes a shinyWidgets::pickerInput() (the layer
selector) and the Bootstrap grid, it must be rendered inside a
Bootstrap page that also carries the .ptr-app theme scope and the
asset bundle. Don't assemble that scaffolding by hand: wrap your
composed pieces in ptr_ui_page(), which is the Bootstrap page and
owns the single .ptr-app scope + the (deduped) assets. For a
navbarPage or bslib root (which ptr_ui_page() does not cover) see
vignette("ggpaintr-tutorial").
For finer control still — placing individual placeholder widgets
independently rather than the whole panel — register a custom placeholder
type; see ptr_define_placeholder_value().
Examples
# Expression form (primary): an unquoted ggplot call.
ptr_ui_controls(
ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point(),
id = "p"
)
#> <div class="form-group shiny-input-container">
#> <label class="control-label" id="p-ptr_layer_select-label" for="p-ptr_layer_select">Layer</label>
#> <select data-state-input="true" id="p-ptr_layer_select" class="selectpicker form-control" autocomplete="off"><option value="ggplot" selected>ggplot</option>
#> <option value="geom_point">geom_point</option></select>
#> </div>
#> <div class="tabbable">
#> <ul class="nav nav-hidden shiny-tab-input" id="p-ptr_layer_tabset" data-tabsetid="6847">
#> <li class="active">
#> <a href="#tab-6847-1" data-toggle="tab" data-bs-toggle="tab" data-value="ggplot">ggplot</a>
#> </li>
#> <li>
#> <a href="#tab-6847-2" data-toggle="tab" data-bs-toggle="tab" data-value="geom_point">geom_point</a>
#> </li>
#> </ul>
#> <div class="tab-content" data-tabsetid="6847">
#> <div class="tab-pane active" data-value="ggplot" id="tab-6847-1">
#> <div id="p-ptr_layer_content_ggplot" class="ptr-layer-content">
#> <div id="p-ggplot_1_1_ppVar_NA_ui" class="shiny-html-output"></div>
#> <div id="p-ggplot_1_2_ppVar_NA_ui" class="shiny-html-output"></div>
#> </div>
#> </div>
#> <div class="tab-pane" data-value="geom_point" id="tab-6847-2">
#> <div class="form-group shiny-input-container">
#> <div class="checkbox">
#> <label>
#> <input id="p-geom_point_checkbox" type="checkbox" class="shiny-input-checkbox" checked="checked"/>
#> <span>Include this layer in the plot</span>
#> </label>
#> </div>
#> </div>
#> <div id="p-ptr_layer_content_geom_point" class="ptr-layer-content"></div>
#> </div>
#> </div>
#> </div>
#> <button id="p-ptr_update_plot" type="button" class="btn btn-default action-button"><span class="action-label">Update plot</span></button>
# String form (fallback): equivalent.
ptr_ui_controls(
"ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point()",
id = "p"
)
#> <div class="form-group shiny-input-container">
#> <label class="control-label" id="p-ptr_layer_select-label" for="p-ptr_layer_select">Layer</label>
#> <select data-state-input="true" id="p-ptr_layer_select" class="selectpicker form-control" autocomplete="off"><option value="ggplot" selected>ggplot</option>
#> <option value="geom_point">geom_point</option></select>
#> </div>
#> <div class="tabbable">
#> <ul class="nav nav-hidden shiny-tab-input" id="p-ptr_layer_tabset" data-tabsetid="4675">
#> <li class="active">
#> <a href="#tab-4675-1" data-toggle="tab" data-bs-toggle="tab" data-value="ggplot">ggplot</a>
#> </li>
#> <li>
#> <a href="#tab-4675-2" data-toggle="tab" data-bs-toggle="tab" data-value="geom_point">geom_point</a>
#> </li>
#> </ul>
#> <div class="tab-content" data-tabsetid="4675">
#> <div class="tab-pane active" data-value="ggplot" id="tab-4675-1">
#> <div id="p-ptr_layer_content_ggplot" class="ptr-layer-content">
#> <div id="p-ggplot_1_1_ppVar_NA_ui" class="shiny-html-output"></div>
#> <div id="p-ggplot_1_2_ppVar_NA_ui" class="shiny-html-output"></div>
#> </div>
#> </div>
#> <div class="tab-pane" data-value="geom_point" id="tab-4675-2">
#> <div class="form-group shiny-input-container">
#> <div class="checkbox">
#> <label>
#> <input id="p-geom_point_checkbox" type="checkbox" class="shiny-input-checkbox" checked="checked"/>
#> <span>Include this layer in the plot</span>
#> </label>
#> </div>
#> </div>
#> <div id="p-ptr_layer_content_geom_point" class="ptr-layer-content"></div>
#> </div>
#> </div>
#> </div>
#> <button id="p-ptr_update_plot" type="button" class="btn btn-default action-button"><span class="action-label">Update plot</span></button>
