11from pathlib import Path
2- from typing import Optional
2+ from typing import Any , Callable , Dict , Optional , Tuple
33
44import streamlit as st
55import 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
3864def 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
60107if __name__ == "__main__" :
61108 main ()
0 commit comments