rstudio / shinyuieditor

A GUI for laying out a Shiny application that generates clean and human-readable UI code
https://rstudio.github.io/shinyuieditor/
MIT License
216 stars 29 forks source link

launch_editor fails when using reactive({}) #148

Closed TiagoOlivoto closed 1 year ago

TiagoOlivoto commented 1 year ago

Hi! First of all, thank you so much for the impressive package!

I've noticed an issue when using reactive({}) in my code. In brief, when using reactive({}), for example, to create an internal data.frame and make it available for several procedures, the command shinyuieditor::launch_editor(app_loc = "...") doesn't open the editor. The shiny application, however, works as expected. Here's a minimal example (assuming that this is saved in app.R within the working directory 'myfolder'

library(shiny)
library(gridlayout)
library(bslib)

ui <- navbarPage(
  title = "Chick Weights",
  selected = "Empty Tab",
  collapsible = TRUE,
  theme = bslib::bs_theme(),
  tabPanel(
    title = "Empty Tab",
    grid_container(
      layout = c(
        "nums square",
        "nums square"
      ),
      row_sizes = c(
        "1fr",
        "1fr"
      ),
      col_sizes = c(
        "1fr",
        "1fr"
      ),
      gap_size = "10px",
      grid_card(
        area = "nums",
        full_screen = TRUE,
        card_header("Header"),
        card_body_fill(
          sliderInput(
            inputId = "inputId",
            label = "Slider Input",
            min = 0,
            max = 10,
            value = 5,
            width = "100%"
          )
        )
      ),
      grid_card(
        area = "square",
        full_screen = TRUE,
        card_header("Header"),
        card_body_fill(textOutput(outputId = "squared"))
      )
    )
  )
)

server <- function(input, output) {
  numsqr <- reactive({input$inputId ^ 2})

output$squared <- renderText({
  paste0("the square of ", input$inputId, " is ", numsqr())
})

}

shinyApp(ui, server)

Then, running

shinyuieditor::launch_editor(app_loc = "myfolder/")

Do not open the editor, as can be seen in the following PrintScreen

dontwork

Now, without reactive() it works

library(shiny)
library(gridlayout)
library(bslib)

ui <- navbarPage(
  title = "Chick Weights",
  selected = "Empty Tab",
  collapsible = TRUE,
  theme = bslib::bs_theme(),
  tabPanel(
    title = "Empty Tab",
    grid_container(
      layout = c(
        "nums square",
        "nums square"
      ),
      row_sizes = c(
        "1fr",
        "1fr"
      ),
      col_sizes = c(
        "1fr",
        "1fr"
      ),
      gap_size = "10px",
      grid_card(
        area = "nums",
        full_screen = TRUE,
        card_header("Header"),
        card_body_fill(
          sliderInput(
            inputId = "inputId",
            label = "Slider Input",
            min = 0,
            max = 10,
            value = 5,
            width = "100%"
          )
        )
      ),
      grid_card(
        area = "square",
        full_screen = TRUE,
        card_header("Header"),
        card_body_fill(textOutput(outputId = "squared"))
      )
    )
  )
)

server <- function(input, output) {
output$squared <- renderText({
  paste0("the square of ", input$inputId, " is ", input$inputId^2)
})

}

shinyApp(ui, server)

works

Could this be only on my side? Best regards!

Created on 2023-03-18 with reprex v2.0.2

nstrayer commented 1 year ago

Oh this is interesting and absolutely not on your side!

If you're curious about what's happening: The logs show these lines:

Error : Problem with standardizing arguments supplied to expression.
Error msg: "object 'numsqr' not found"

Because when the editor parses your app file, it tries to fill in arguments for functions that may be given without names but actually have names. E.g. tabPanel("Empty Tab", grid_container(...)) is equal to tabPanel(title = "Empty Tab", grid_container(...)). This is so it knows what function arguments are settings like title as opposed to you wanting to place a child element in tabPanel with the content "Empty Tab"`.

What I failed to do is account for reactives that become functions but don't have a set of known named parameters. How I avoided this is beyond me but I really appreciate you catching it and providing a super reproducable example.

A fix should be coming soon!

nstrayer commented 1 year ago

Okay, so Pr #149 will fix this once it's merged. Turns out the problem was even more general than reactives, but any function call that wasn't a function previously known.

Here's the result of running the first app above with the code from the PR.

Shiny UI Editor

nstrayer commented 1 year ago

Okay. PR merged. You should be good to update with remotes::install_github("rstudio/shinyuieditor") and things should be resolved. Thanks so much for the clear and helpful issue! It really helps drive the project forward!

TiagoOlivoto commented 1 year ago

Thank you so much for your prompt fix! I'll try it later.... this will save me a lot of code since I was generating the data inside each render***({}). Best regards!