Trabalhando com função dentro de um módulo em Shiny: cannot coerce type ‘closure’ to vector of type ‘character’

Pessoal,
My idea is to create multiple elements that have radioGroupButtons and plotlyOutput in a module file. To avoid repetitions I created a function like this bellow:

A minha ideia é criar na ui do shiny conjuntos de radioGroupButtons e plotlyOutput. Eu estou usando modulos e aí esta ficando complicado.

Abaixo é a função de radioGroupButtons e plotlyOutput que criei:

tabpanel_content <- function(radio_id, plotly_id){
  div(
    id = "div_1",
    style = "",

    div(
      class = "inputs ",
      style = "width: 100%",

      radioGroupButtons(
        inputId = NS(radio_id),
        label = "Radio",
        choices = c("Input_1","Input_2"),
        status = "success"
      )
    ),

    div(plotlyOutput(outputId = NS(plotly_id), height = 200,width = "auto"))
  )
}

Em seguida colo essa funcao no modulo:

mod_1_UI <- function(id) {
  ns <- NS(id)
  tagList(

    tabsetPanel(

      tabPanel(
        strong("TabPanel - Title"),

        tabpanel_content(radio_id = 'radio_input',plotly_id = 'plotly_chart_1')

  )))
}

mod_1_Server <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {

    }
  )
}

E depois puxo no app do Shiny:

library(shiny)
library(shinyWidgets)
library(plotly)


source(file = 'module_1.R')
source(file = 'input_functions_1.R')

ui <- fluidPage(

  mod_1_UI("mod_1")

)

server <- function(input, output, session) {

  mod_1_Server("mod_1")

}

shinyApp(ui, server)

Mas tenho o seguinte erro: cannot coerce type ‘closure’ to vector of type ‘character’

Eu tenho a impressão que se trata de uma mudança básica. Mas ja fiz de tudo por aqui.

Alguma ajuda?

Diogo,

O problema está nos NS() que você usa dentro de tabpanel_content(). Uma forma eficiente de debugar código Shiny é simplesmente executar cada bloco de código e verificar se a saída é um HTML válido:

library(shiny)
library(shinyWidgets)

# ID declarado no mod_1_UI()
radio_id <- "radio_input"

# A saída disso é uma função!
NS(radio_id)
#> function (id) 
#> {
#>     if (length(id) == 0) 
#>         return(ns_prefix)
#>     if (length(ns_prefix) == 0) 
#>         return(id)
#>     paste(ns_prefix, id, sep = ns.sep)
#> }
#> <bytecode: 0x12bf3e640>
#> <environment: 0x12bf3dca0>

# O inputId espera uma string, não uma função
radioGroupButtons(
  inputId = NS(radio_id),
  label = "Radio",
  choices = c("Input_1", "Input_2"),
  status = "success"
)
#> Error in paste0(inputId, "-label"): cannot coerce type 'closure' to vector of type 'character'

# Agora sim
radioGroupButtons(
  inputId = radio_id,
  label = "Radio",
  choices = c("Input_1", "Input_2"),
  status = "success"
)
#> <div class="form-group shiny-input-container shiny-input-radiogroup shiny-input-container-inline">
#>   <label id="radio_input-label" class="control-label" for="radio_input">Radio</label>
#>   <br/>
#>   <div id="radio_input" class="radio-group-buttons">
#>     <div aria-labelledby="radio_input-label" class="btn-group btn-group-container-sw" data-toggle="buttons" role="group">
#>       <div class="btn-group btn-group-toggle" role="group">
#>         <button class="btn radiobtn btn-success active">
#>           <input type="radio" autocomplete="off" name="radio_input" value="Input_1" checked="checked"/>
#>           Input_1
#>         </button>
#>       </div>
#>       <div class="btn-group btn-group-toggle" role="group">
#>         <button class="btn radiobtn btn-success">
#>           <input type="radio" autocomplete="off" name="radio_input" value="Input_2"/>
#>           Input_2
#>         </button>
#>       </div>
#>     </div>
#>   </div>
#> </div>

Created on 2022-07-28 by the reprex package (v2.0.1)

No final, a função tabpanel_content() fica assim:

tabpanel_content <- function(radio_id, plotly_id) {
  div(
    id = "div_1",
    style = "",

    div(
      class = "inputs ",
      style = "width: 100%",

      radioGroupButtons(
        inputId = radio_id,
        label = "Radio",
        choices = c("Input_1", "Input_2"),
        status = "success"
      )
    ),

    div(plotlyOutput(outputId = plotly_id, height = 200, width = "auto"))
  )
}
1 curtida