fasthtml
fasthtml copied to clipboard
[BUG] Missing function type hints result in `None` for function inputs in FastHTML
Description
When using FastHTML, omitting type hints for function parameters causes input values to default to None, resulting in a TypeError. This behavior is inconsistent with the expected functionality where inputs should retain their values regardless of type hints.
Issue
Below is a sample code (adapted from FastHTML Tutorials):
import fasthtml.components as fh_components
from fasthtml.core import FastHTML, serve
app = FastHTML()
route = app.route
@app.get("/")
def home():
return fh_components.Form(
fh_components.Input(type="text", id="input_1", name="input 1"),
fh_components.Input(type="text", id="input_2", name="input 2"),
fh_components.Button("Submit", id="submit", hx_post="/submit", hx_target="#response"),
), fh_components.Div(id="response")
@app.post("/submit")
def demo_fn(input_1: str, input_2: str):
response = inp_1 + " " + inp_2
return response
serve()
The above code works perfectly!
but if we change the demo_fn removing the type hints as:
@app.post("/submit")
def demo_fn(input_1, input_2):
response = inp_1 + " " + inp_2
return response
This throws error:
File "/workspaces/demoapp/test.py", line 17, in demo_fn
response = inp_1 + " " + inp_2
~~~~~~^~~~~
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'
on debugging, we found that missing types are making the values None for some weird reason.
This must be a bug in how fastHTL handles the data!
Expected behavior
FastHTML should not convert the function inputs to None if the function input param type hints are missing.
Found workaround/fix
A workaround was found, by tapping into the form request. but this should work without this hack/workaround. here is the workaround:
import fasthtml.components as fh_components
from fasthtml.core import FastHTML, serve, Request
app = FastHTML()
route = app.route
@app.get("/")
def home():
return fh_components.Form(
fh_components.Input(type="text", id="input_1", name="input 1"),
fh_components.Input(type="text", id="input_2", name="input 2"),
fh_components.Button("Submit", id="submit", hx_post="/submit", hx_target="#response"),
), fh_components.Div(id="response")
@app.post("/submit")
async def demo_fn(request: Request):
form_data = await request.form()
input_1 = form_data.get("input_1")
input_2 = form_data.get("input_2")
return input_1 + input_2
serve()
PS: discovered this bug & workaround while working on a project with @soumik12345