Command API

Overview

shiny.webawesome is generator-first, but it also provides a narrow command/helper layer for advanced cases that are outside the generated wrapper, binding, and update-helper surface.

This layer is useful for cases where you need to:

These helpers are intentionally narrow. They are not meant to grow into a second per-component API alongside the generated wrapper surface.

This small executed example prints the emitted <script> tag used for inline browser glue:

library(shiny.webawesome)

js_helper <- wa_js("console.log('shiny.webawesome command api vignette');")
cat(as.character(js_helper), sep = "\n")
## <script>console.log('shiny.webawesome command api vignette');</script>

Design Philosophy

The package’s command layer is an escape hatch, not the default way to work with components.

Prefer:

Use the command layer when you need browser-side interaction that is outside those supported generated paths.

Use wa_js() when the missing piece is app-local browser glue rather than a server-to-browser command.

Server-to-Browser Commands

The package currently exposes two user-facing server-side command helpers:

Internally, these use a custom Shiny message channel named "shiny.webawesome.command".

wa_set_property()

wa_set_property() sends a one-way command from the Shiny server that assigns a live browser-side property on the target element.

This is useful when a component property needs to change from server logic but the package does not already provide a generated update helper for that field.

On the server side, wa_set_property() validates only the helper inputs such as the target id, property name, and session. It does not validate whether the requested property exists on the browser-side element.

In the browser runtime, the command layer validates that the DOM id resolves to an element and that a property name was supplied, then assigns the value directly. Warning messages for this command path are controlled by the package warning registry, especially the command_layer key. For details, refer to the Package Options article.

library(shiny)
library(shiny.webawesome)

ui <- webawesomePage(
  title = "Set property",
  actionButton("open_dialog", "Open dialog"),
  wa_dialog(
    "dialog",
    label = "Example dialog",
    "Dialog body"
  )
)

server <- function(input, output, session) {
  observeEvent(input$open_dialog, {
    wa_set_property("dialog", "open", TRUE, session = session)
  })
}

shinyApp(ui, server)

wa_call_method()

wa_call_method() sends a one-way command from the Shiny server that invokes a browser-side method on the target element.

This is useful when the component already exposes a meaningful browser-side method and you want to trigger it directly from server logic.

On the server side, wa_call_method() validates only the helper inputs such as the target id, method name, argument list, and session. It does not validate whether the requested method exists on the browser-side element.

In the browser runtime, the command layer validates that the DOM id resolves to an element, that a method name was supplied, and that the named member is callable on the target element before invoking it. Warning messages for this command path are controlled by the package warning registry, especially the command_layer key. For details, refer to the Package Options article.

library(shiny)
library(shiny.webawesome)

ui <- webawesomePage(
  title = "Call method",
  actionButton("show_details", "Show details"),
  actionButton("hide_details", "Hide details"),
  wa_details(
    "details",
    summary = "More information",
    "Details body"
  )
)

server <- function(input, output, session) {
  observeEvent(input$show_details, {
    wa_call_method("details", "show", session = session)
  })

  observeEvent(input$hide_details, {
    wa_call_method("details", "hide", session = session)
  })
}

shinyApp(ui, server)

Both helpers target elements by DOM id, so the component must have a stable browser id available.

Browser Glue

wa_js() serves a different purpose from the server-side command helpers.

Use it when the missing piece is a small amount of browser-local logic that is easier to express directly in JavaScript than through a server-to-browser command.

Typical uses include:

library(shiny)
library(shiny.webawesome)

ui <- webawesomePage(
  title = "Browser glue",
  wa_js("
    function publishDialogState() {
      const dialog = document.getElementById('dialog');

      if (!dialog ||
          !window.Shiny ||
          typeof window.Shiny.setInputValue !== 'function') {
        return;
      }

      window.Shiny.setInputValue(
        'dialog_open_state',
        dialog.open,
        { priority: 'event' }
      );
    }

    document.addEventListener('wa-show', function(event) {
      if (event.target.id === 'dialog') {
        publishDialogState();
      }
    });

    document.addEventListener('wa-after-hide', function(event) {
      if (event.target.id === 'dialog') {
        publishDialogState();
      }
    });
  "),
  wa_dialog(
    "dialog",
    label = "Example dialog",
    "Dialog body"
  ),
  verbatimTextOutput("dialog_state")
)

server <- function(input, output, session) {
  output$dialog_state <- renderPrint({
    input$dialog_open_state
  })
}

shinyApp(ui, server)

wa_js() should stay small and app-local. For larger or shared scripts, prefer standard Shiny asset patterns.

Diagnostics and Limits

The command layer is intentionally conservative.

It does not validate that:

The package’s warning/diagnostic options include:

These control warning and debug output for the runtime command bridge.

For example:

options(
  shiny.webawesome.warnings = list(
    command_layer_debug = TRUE
  )
)

Choosing the Right Tool

Use:

If you find yourself building a large handwritten command or browser-glue layer, that is usually a sign to step back and choose a different approach: extend the supported package surface where appropriate, or move the logic into standard Shiny/JavaScript asset patterns rather than stretching these helpers beyond their intended scope.