Skip to content

Commit 5b5cd3c

Browse files
authored
Merge pull request #7 from blackary/on-change
Add on_change keyword
2 parents 3c8ba48 + 92eb145 commit 5b5cd3c

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
setuptools.setup(
99
name="streamlit-keyup",
10-
version="0.1.7",
10+
version="0.1.8",
1111
author="Zachary Blackwood",
1212
author_email="[email protected]",
1313
description="Text input that renders on keyup",

src/st_keyup/__init__.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from pathlib import Path
2-
from typing import Optional
2+
from typing import Any, Callable, Dict, Optional, Tuple
33

44
import streamlit as st
55
import streamlit.components.v1 as components
@@ -13,6 +13,9 @@ def st_keyup(
1313
value: str = "",
1414
key: Optional[str] = None,
1515
debounce: int = 0,
16+
on_change: Optional[Callable] = None,
17+
args: Optional[Tuple[Any, ...]] = None,
18+
kwargs: Optional[Dict[str, Any]] = None,
1619
):
1720
"""
1821
Generate a text input that renders on keyup, debouncing the input by the
@@ -23,7 +26,16 @@ def st_keyup(
2326
when the user is typing. Since the input updating will cause the app to rerun,
2427
if you are having performance issues, you should consider setting a debounce
2528
value.
29+
30+
on_change is a callback function that will be called when the value changes.
31+
32+
args and kwargs are optional arguments which are passed to the on_change callback
33+
function
2634
"""
35+
36+
if key is None:
37+
key = "st_keyup_" + label
38+
2739
component_value = _component_func(
2840
label=label,
2941
value=value,
@@ -32,10 +44,26 @@ def st_keyup(
3244
default=value,
3345
)
3446

47+
if on_change is not None:
48+
if "__previous_values__" not in st.session_state:
49+
st.session_state["__previous_values__"] = {}
50+
51+
if component_value != st.session_state["__previous_values__"].get(key, value):
52+
st.session_state["__previous_values__"][key] = component_value
53+
54+
if on_change:
55+
if args is None:
56+
args = ()
57+
if kwargs is None:
58+
kwargs = {}
59+
on_change(*args, **kwargs)
60+
3561
return component_value
3662

3763

3864
def main():
65+
from datetime import datetime
66+
3967
st.write("## Default keyup input")
4068
value = st_keyup("Enter a value")
4169

@@ -47,15 +75,34 @@ def main():
4775
st.write(value)
4876

4977
"## Keyup input with 500 millesecond debounce"
50-
value = st_keyup("Enter a second value", debounce=500)
78+
value = st_keyup("Enter a second value debounced", debounce=500)
5179

5280
st.write(value)
5381

82+
def on_change():
83+
st.write("Value changed!", datetime.now())
84+
85+
def on_change2(*args, **kwargs):
86+
st.write("Value changed!", args, kwargs)
87+
88+
"## Keyup input with on_change callback"
89+
value = st_keyup("Enter a third value", on_change=on_change)
90+
91+
"## Keyup input with on_change callback and debounce"
92+
value = st_keyup("Enter a third value...", on_change=on_change, debounce=1000)
93+
st.write(value)
94+
95+
"## Keyup input with args"
96+
value = st_keyup("Enter a fourth value...", on_change=on_change2, args=("Hello", "World"), kwargs={"foo": "bar"})
97+
st.write(value)
98+
5499
"## Standard text input for comparison"
55100
value = st.text_input("Enter a value")
56101

57102
st.write(value)
58103

104+
st.write(st.session_state)
105+
59106

60107
if __name__ == "__main__":
61108
main()

0 commit comments

Comments
 (0)