Skip to content

Commit

Permalink
Merge pull request #8 from shunichironomura/bare-annotated-model
Browse files Browse the repository at this point in the history
Add widget_builder parameter to st_auto_form
  • Loading branch information
shunichironomura authored Jan 18, 2024
2 parents 43769ec + d4531ef commit a6df740
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 9 deletions.
32 changes: 28 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,31 @@ with st_auto_form("form_2", model=ParentFormModel) as parent_form:

### Custom Widget

You can define a custom widget by defining a custom `WidgetBuilder`.
You can define a custom widget by defining a custom `WidgetBuilder` and pass it to `st_auto_form` as `widget_builder`.

```python
from typing import Annotated

import streamlit as st
from pydantic import BaseModel

from streamlit_pydantic_form import st_auto_form, widget

# Custom widget builder
class PointWidget(widget.WidgetBuilder):
def build(self) -> PointModel:
x = st.slider("X")
y = st.slider("Y")
return PointModel(x=x, y=y)

with st_auto_form("form_3", model=PointModel, widget_builder=PointWidget()) as point_form:
val3 = point_form.input_widgets()
submitted = st.form_submit_button("Submit")
if submitted:
st.write("x", val3.x, "y", val3.y)
```

You can also use the `Annotated` type hint to define a custom widget.

```python
from typing import Annotated
Expand All @@ -110,9 +134,9 @@ class PointWidget(widget.WidgetBuilder):
class PointFormModel(BaseModel):
p: Annotated[PointModel, PointWidget()]

with st_auto_form("form_3", model=PointFormModel) as point_form:
val3 = point_form.input_widgets()
with st_auto_form("form_4", model=PointFormModel) as point_form2:
val4 = point_form2.input_widgets()
submitted = st.form_submit_button("Submit")
if submitted:
st.write("p", val3.p)
st.write("x", val4.p.x, "y", val4.p.y)
```
19 changes: 14 additions & 5 deletions example_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,30 @@ class PointModel(BaseModel):
y: int


# Custom widget
# Custom widget builder
class PointWidget(widget.WidgetBuilder):
def build(self) -> PointModel:
x = st.slider("X")
y = st.slider("Y")
return PointModel(x=x, y=y)


# Form model
with st_auto_form("form_3", model=PointModel, widget_builder=PointWidget()) as point_form:
val3 = point_form.input_widgets()
submitted = st.form_submit_button("Submit")
if submitted:
st.write("x", val3.x, "y", val3.y)

st.markdown("# Custom widget example 2")


# Combination of custom and annotated widgets
class PointFormModel(BaseModel):
p: Annotated[PointModel, PointWidget()]


with st_auto_form("form_3", model=PointFormModel) as point_form:
val3 = point_form.input_widgets()
with st_auto_form("form_4", model=PointFormModel) as point_form2:
val4 = point_form2.input_widgets()
submitted = st.form_submit_button("Submit")
if submitted:
st.write("p", val3.p)
st.write("x", val4.p.x, "y", val4.p.y)
4 changes: 4 additions & 0 deletions streamlit_pydantic_form/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ def __init__(
model: type[_T],
clear_on_submit: bool = False,
border: bool = True,
widget_builder: WidgetBuilder | None = None,
) -> None:
self.key = key
self.model = model
self.clear_on_submit = clear_on_submit
self.border = border
self.form = st.form(key=self.key, clear_on_submit=self.clear_on_submit)
self.widget_builder = widget_builder

def input_widgets(self) -> _T:
if self.widget_builder is not None:
return self.widget_builder.build()
return _model_to_input_components(self.model)

@deprecated(
Expand Down

0 comments on commit a6df740

Please sign in to comment.