posit-dev / posit-dev/py-shiny
Input binding from HTML/Javascript inside @module.server
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.8k
- Forks
- 135
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 21
Description
Hi everyone, i'm facing this problem using custom input from HTML page and shiny modules.
Here's a small example on how to reproduce it:
app.py
from shiny import App, ui, reactive
from pathlib import Path
from modules.viewer import viewer_server, viewer_ui
app_ui = ui.page_fluid(
ui.panel_title("Hello Shiny!"),
ui.panel_main(
viewer_ui("viewer"),
))
def server(input, output, session):
viewer_server("viewer")
@reactive.Effect
def _():
print("Catch input file from main server: ", input.file_upload())
return input.file_upload()
www_dir = Path(__file__).parent / "frontend"
app = App(app_ui, server, static_assets=www_dir)
viewer.py
from pathlib import Path
from shiny import render, ui, Inputs, Outputs, Session, module, reactive
@module.ui
def viewer_ui():
return ui.output_ui('viewer')
@module.server
def viewer_server(input: Inputs, output: Outputs, session: Session):
@reactive.Effect
def _():
print("Catch input file from module: ", input.file_upload())
return input.file_upload()
@output
@render.ui
def viewer():
return ui.HTML((Path("frontend") / "index.html").read_text())
and the index.html page:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>shiny-ifc.js</title>
<script type="module" src="./main.js"></script>
</head>
<body>
<input type="file" id="file_upload" accept=".ifc" name="file_upload" multiple="false" />
<div> A 3D Viewer with THREE.js..</div>
</body>
</html>
Once a file is uploaded, only the print inside app.py gets fired.
The same behaviour happens using Shiny object inside main.js using setInputValue
main.js
const input = document.getElementById("file_upload");
input.addEventListener("change", async (e) => {
const file = input.files[0];
const ifcURL = URL.createObjectURL(file);
Shiny.setInputValue("file_upload", { name: file.name, url: ifcURL });
});
Moreover, I would like to understand why the uploaded file caught from Shiny has an MME type of octet-stream while the ones on javascript are a Blob.
Thanks in advance!
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the minimal reproduction using app.py, viewer.py, frontend/index.html, and main.js; compare the input.file_upload() effects in the main server and @module.server. Then inspect the input-binding path for module namespacing and file/MIME handling. Done means the module behavior and the octet-stream versus Blob distinction are explained, with a verified fix or documented limitation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, python
- Domain
- backend, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100