Bind widgets to query params - st.datetime_input & st.time_input#14103
Bind widgets to query params - st.datetime_input & st.time_input#14103mayagbarnes merged 7 commits intodevelopfrom
st.datetime_input & st.time_input#14103Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
✅ PR preview is ready!
|
There was a problem hiding this comment.
Pull request overview
This PR adds bind="query-params" support to st.datetime_input and st.time_input, enabling two-way synchronization between widget values and URL query parameters. It follows the same patterns established in #14034 for st.date_input.
Changes:
- Wire format modernization for
st.datetime_input: Internal protobuf format changed fromYYYY/MM/DD, HH:mmto ISO 8601 (YYYY-MM-DDThh:mm) with backward-compatible fallback parsing in both frontend and backend - Query param binding implementation: Both widgets support
bind="query-params"with proper clearability, error handling for invalid/out-of-bounds values, and seamless URL synchronization - Comprehensive test coverage: Python unit tests, frontend tests, and E2E tests verify binding functionality, invalid value handling, clearability, and out-of-bounds behavior
Reviewed changes
Copilot reviewed 17 out of 20 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
proto/streamlit/proto/TimeInput.proto |
Added optional query_param_key field for query param binding |
proto/streamlit/proto/DateTimeInput.proto |
Added optional query_param_key field for query param binding |
lib/streamlit/elements/widgets/time_widgets.py |
Wire format updated to ISO 8601, bind parameter added to both widgets, serdes updated with fallback parsing, clearability logic |
lib/tests/streamlit/typing/time_input_types.py |
Type tests for bind parameter with time_input |
lib/tests/streamlit/typing/datetime_input_types.py |
Type tests for bind parameter with datetime_input |
lib/tests/streamlit/elements/time_input_test.py |
Unit tests for query param binding, serde format parsing, invalid value handling |
lib/tests/streamlit/elements/datetime_input_test.py |
Unit tests for query param binding, ISO format parsing with legacy fallback, out-of-bounds handling |
lib/streamlit/testing/v1/element_tree.py |
AppTest support for new ISO format with legacy fallback parsing |
frontend/lib/src/components/widgets/TimeInput/TimeInput.tsx |
Query param binding setup with queryParamBinding config |
frontend/lib/src/components/widgets/TimeInput/TimeInput.test.tsx |
Frontend tests for query param registration, clearability, unregistration |
frontend/lib/src/components/widgets/DateTimeInput/dateTimeInputUtils.ts |
Wire format updated to ISO 8601, fallback parsing for legacy format |
frontend/lib/src/components/widgets/DateTimeInput/DateTimeInput.tsx |
Query param binding setup with queryParamBinding config |
frontend/lib/src/components/widgets/DateTimeInput/DateTimeInput.test.tsx |
Frontend tests updated for new wire format, query param binding tests added |
e2e_playwright/st_time_input.py |
Three bound time input widgets added for E2E testing |
e2e_playwright/st_time_input_test.py |
E2E tests for seeding, clearable, invalid values, step non-snapping |
e2e_playwright/st_datetime_input.py |
Three bound datetime input widgets added for E2E testing |
e2e_playwright/st_datetime_input_test.py |
E2E tests for seeding, clearable, invalid values, out-of-range handling |
e2e_playwright/__snapshots__/linux/st_time_input_test/*.png |
Updated snapshots reflecting new widget count (13→16) |
SummaryThis PR adds
The implementation follows the patterns established in PR #14034 for Code QualityThe code is well-structured, clean, and follows existing Streamlit patterns closely. Specific observations:
One inconsistency found — In if value_needs_reset and key is not None:
# Update session_state so subsequent accesses in this run
# return the corrected value. Use reset_state_value to avoid
# the "cannot be modified after widget instantiated" error.
get_session_state().reset_state_value(key, current_value)Compare with if value_needs_reset and key is not None:
# Update session_state so subsequent accesses in this run
# return the corrected value. Use reset_state_value to avoid
# the "cannot be modified after widget instantiated" error.
get_session_state().reset_state_value(key, current_value)
# Clear stale URL param when an out-of-bounds URL value was reset.
if bind == "query-params":
with get_session_state().query_params() as qp:
qp.remove_param(str(key))This means that if a user has Test CoverageTest coverage is comprehensive across all layers:
The Backwards CompatibilityThis change is fully backward-compatible:
Security & RiskNo security concerns identified:
Low risk of regression: The wire format change is internal and protected by dual-format parsing. The only regression risk is in the edge case noted in Code Quality (stale URL params with dynamic bounds), which is a minor inconsistency rather than a correctness bug. AccessibilityNo accessibility concerns. The widgets already have proper Recommendations
if bind == "query-params":
with get_session_state().query_params() as qp:
qp.remove_param(str(key))VerdictAPPROVED: Well-implemented feature that follows established patterns with comprehensive test coverage. The missing URL param clearing for the dynamic bounds edge case (recommendation #1) is a minor inconsistency that could be addressed as a follow-up. This is an automated AI review by |
Describe your changes
Adds
bind="query-params"tost.datetime_inputandst.time_inputfor two-way sync between widget values and URL query parameters.Key changes:
st.datetime_inputwire format modernized to ISO 8601: The internal protobuf wire format is changed fromYYYY/MM/DD, HH:mmtoYYYY-MM-DDThh:mm(e.g.,2025-01-15T16:45). This is an internal-only change — the user-facing display format (controlled by theformatparameter) is unaffected. Both frontend and backend parsers accept both formats, so backward compatibility is maintained via fallback parsing.st.datetime_inputbinding: Usesstring_array_valuefor the proto value type. URL format:?my_dt=2025-01-15T16:45. Clearable whenvalue=None(empty URL param?my_dt=clears toNone), non-clearable otherwise.st.time_inputbinding: Usesstring_valuefor the proto value type. URL format:?my_time=14:30. Clearable whenvalue=None, non-clearable otherwise.?my_dt=not-a-datetime) silently revert to the widget's default value, matching the pattern used byst.date_input,st.radio, andst.selectbox.min_value/max_value) are reset to the widget default, and the stale URL param is explicitly cleared.st.date_input#14034 forst.date_input.Testing Plan