posit-dev / shinylive

Run Shiny on Python and R (compiled to wasm) in the browser
https://shinylive.io/py/examples/
MIT License
203 stars 15 forks source link

External files or multifile app does not work #77

Open berkorbay opened 11 months ago

berkorbay commented 11 months ago

Hi. Just started testing shinylive and I have a quick question. I need either a small json file for my app.py or an external module (not pip install just a local wordlist.py file). When I wanted to use shinylive for my app (and files) inside app/ folder and I want to export the outputs to docs/ folder. I use the following command.

shinylive export app docs

When I serve it on the localhost with python3 -m http.server --directory docs --bind localhost 8008 I get the following result.

Screenshot 2023-11-13 at 14 36 09

I know it can be done due to this example: https://shinylive.io/py/examples/#regularization

Perhaps I missed a documentation for multi-file shinylive apps. I can do a workaround with a bloated app.py but knowing how to work with multiple files will be incredible.

Thanks for such an awesome package. It will get better and better I presume.

DOH-FAA3303 commented 2 months ago

+1

I'm having a hard time modularizing an app. I have the server and ui broken into parts like this:

server.R

server <- function(input, output) {

  # choose columns to display
  diamonds2 = diamonds[sample(nrow(diamonds), 1000), ]
  output$mytable1 <- DT::renderDataTable({
    DT::datatable(diamonds2[, input$show_vars, drop = FALSE])
  })

  # sorted columns are colored now because CSS are attached to them
  output$mytable2 <- DT::renderDataTable({
    DT::datatable(mtcars, options = list(orderClasses = TRUE))
  })

  # customize the length drop-down menu; display 5 rows per page by default
  output$mytable3 <- DT::renderDataTable({
    DT::datatable(iris, options = list(lengthMenu = c(5, 30, 50), pageLength = 5))
  })
}

ui.R

library(shiny)
library(ggplot2)  # for the diamonds dataset
print('hi')
ui <- fluidPage(
  title = "Examples of DataTables",
  sidebarLayout(
    sidebarPanel(
      conditionalPanel(
        'input.dataset === "diamonds"',
        checkboxGroupInput("show_vars", "Columns in diamonds to show:",
                           names(diamonds), selected = names(diamonds))
      ),
      conditionalPanel(
        'input.dataset === "mtcars"',
        helpText("Click the column header to sort a column.")
      ),
      conditionalPanel(
        'input.dataset === "iris"',
        helpText("Display 5 records by default.")
      )
    ),
    mainPanel(
      tabsetPanel(
        id = 'dataset',
        tabPanel("diamonds", DT::dataTableOutput("mytable1")),
        tabPanel("mtcars", DT::dataTableOutput("mytable2")),
        tabPanel("iris", DT::dataTableOutput("mytable3"))
      )
    )
  )
)

and ideally it would be simple to source both into a qmd like this

---
title: modular shiny
---

# App
```{shinylive-r}
source("server.R")
source("ui.R")

shinyApp(ui,server)


I've tried other methods, like using the `#| file: server.R` param in a code chunk, wrapping the code in special knitr comments `## ---- link` and calling them into the code chunk, and using the include shortcode, but no luck. Looks like for now we just need to put the entire app into one code chunk?
gadenbuie commented 2 months ago

I've tried other methods, like using the #| file: server.R param in a code chunk,

Hi @DOH-FAA3303, I think I see your issue: the special comment should be ## file: server.R (note the initial ## and not #|). That likely explains all of the problems you listed, but if not can you please open an issue over in https://github.com/quarto-ext/shinylive (the repo for the Quarto shinylive extension). Thanks!

DOH-FAA3303 commented 2 months ago

@gadenbuie I'm trying to modularize my shiny app and keep the app from being one giant file. the ##: file function doesn't appear to call in a specific file in my directory.

So i mean i have a tree like this

├── index.qmd
├── src
│   ├── server.R
│   └── ui.R

where i want to call in different files from the src folder into the index.qmd and not have my entire app within the shinylive-r code chunk.

this might not be an option currently. might need to have a workaround like this https://github.com/quarto-ext/shinylive/issues/13

or do what's mentioned in this youtube video and source the function from github (and dont source it locally), but this didn't work for me https://youtu.be/8SHTj5QYQuc?si=3lxrejhsyHde9_uI&t=816

DOH-FAA3303 commented 2 months ago

nvm I see that you answered this here and you made a shortcode for it! https://github.com/quarto-ext/shinylive/issues/37#issuecomment-1954438837

gadenbuie commented 2 months ago

@DOH-FAA3303 glad you found that comment! We need to update the shinylive extension docs. In your example, the include shortcode should be enough:

# index.qmd

```{shinylive-r}
#| standalone: true
#| viewerHeight: 600

## file: ui.R
{{< include src/ui.R >}}

## file: server.R
{{< include src/server.R >}}