diff --git a/py/examples/textbox.py b/py/examples/textbox.py
index 2872b7cd9ea..22b4de7af96 100644
--- a/py/examples/textbox.py
+++ b/py/examples/textbox.py
@@ -6,7 +6,7 @@
@app('/demo')
async def serve(q: Q):
- if q.args.show_inputs:
+ if q.args.show_inputs or q.args.textbox_submit:
q.page['example'].items = [
ui.text(f'textbox={q.args.textbox}'),
ui.text(f'textbox_disabled={q.args.textbox_disabled}'),
@@ -20,11 +20,7 @@ async def serve(q: Q):
ui.text(f'textbox_placeholder={q.args.textbox_placeholder}'),
ui.text(f'textbox_disabled_placeholder={q.args.textbox_disabled_placeholder}'),
ui.text(f'textbox_multiline={q.args.textbox_multiline}'),
- ui.button(name='show_form', label='Back', primary=True),
- ]
- elif q.args.enter_key_handler:
- q.page['example'].items = [
- ui.text(f'textbox_enter_key_handler={q.args.enter_key_handler}'),
+ ui.text(f'textbox_enter={q.args.textbox_enter}'),
ui.button(name='show_form', label='Back', primary=True),
]
else:
@@ -41,7 +37,7 @@ async def serve(q: Q):
ui.textbox(name='textbox_placeholder', label='With placeholder', placeholder='I need some input'),
ui.textbox(name='textbox_disabled_placeholder', label='Disabled with placeholder', disabled=True,
placeholder='I am disabled'),
- ui.textbox(name='enter_key_handler', label='Submits the textbox value on Enter key', icon='Search'),
+ ui.textbox(name='textbox_submit', label='Submits on enter pressed', icon='Search', submit=True),
ui.textbox(name='textbox_multiline', label='Multiline textarea', multiline=True),
ui.button(name='show_inputs', label='Submit', primary=True),
])
diff --git a/py/h2o_wave/types.py b/py/h2o_wave/types.py
index 9af0aa771cd..26fc740edc5 100644
--- a/py/h2o_wave/types.py
+++ b/py/h2o_wave/types.py
@@ -946,6 +946,7 @@ def __init__(
height: Optional[str] = None,
visible: Optional[bool] = None,
tooltip: Optional[str] = None,
+ submit: Optional[bool] = None,
):
self.name = name
"""An identifying name for this component."""
@@ -983,6 +984,8 @@ def __init__(
"""True if the component should be visible. Defaults to true."""
self.tooltip = tooltip
"""An optional tooltip message displayed when a user clicks the help icon to the right of the component."""
+ self.submit = submit
+ """True if the form should be submitted when enter key pressed."""
def dump(self) -> Dict:
"""Returns the contents of this object as a dict."""
@@ -1007,6 +1010,7 @@ def dump(self) -> Dict:
height=self.height,
visible=self.visible,
tooltip=self.tooltip,
+ submit=self.submit,
)
@staticmethod
@@ -1032,6 +1036,7 @@ def load(__d: Dict) -> 'Textbox':
__d_height: Any = __d.get('height')
__d_visible: Any = __d.get('visible')
__d_tooltip: Any = __d.get('tooltip')
+ __d_submit: Any = __d.get('submit')
name: str = __d_name
label: Optional[str] = __d_label
placeholder: Optional[str] = __d_placeholder
@@ -1050,6 +1055,7 @@ def load(__d: Dict) -> 'Textbox':
height: Optional[str] = __d_height
visible: Optional[bool] = __d_visible
tooltip: Optional[str] = __d_tooltip
+ submit: Optional[bool] = __d_submit
return Textbox(
name,
label,
@@ -1069,6 +1075,7 @@ def load(__d: Dict) -> 'Textbox':
height,
visible,
tooltip,
+ submit,
)
diff --git a/py/h2o_wave/ui.py b/py/h2o_wave/ui.py
index 098ec0789b5..2d3b699302e 100644
--- a/py/h2o_wave/ui.py
+++ b/py/h2o_wave/ui.py
@@ -450,6 +450,7 @@ def textbox(
height: Optional[str] = None,
visible: Optional[bool] = None,
tooltip: Optional[str] = None,
+ submit: Optional[bool] = None,
) -> Component:
"""Create a text box.
@@ -476,6 +477,7 @@ def textbox(
height: The height of the text box, e.g. '100px'. Applicable only if `multiline` is true.
visible: True if the component should be visible. Defaults to true.
tooltip: An optional tooltip message displayed when a user clicks the help icon to the right of the component.
+ submit: True if the form should be submitted when enter key pressed.
Returns:
A `h2o_wave.types.Textbox` instance.
"""
@@ -498,6 +500,7 @@ def textbox(
height,
visible,
tooltip,
+ submit,
))
diff --git a/ui/src/textbox.test.tsx b/ui/src/textbox.test.tsx
index 71eb12ab687..9e854928463 100644
--- a/ui/src/textbox.test.tsx
+++ b/ui/src/textbox.test.tsx
@@ -102,8 +102,8 @@ describe('Textbox.tsx', () => {
expect(syncMock).not.toBeCalled()
})
- it('Calls sync on enter pressed', () => {
- const { getByTestId } = render()
+ it('Calls sync on enter pressed - submit specified', () => {
+ const { getByTestId } = render()
const syncMock = jest.fn()
T.qd.sync = syncMock
@@ -112,8 +112,8 @@ describe('Textbox.tsx', () => {
expect(syncMock).toBeCalled()
})
- it('Does not call sync when key pressed is not enter', () => {
- const { getByTestId } = render()
+ it('Does not call sync when key pressed is not enter - submit specified', () => {
+ const { getByTestId } = render()
const syncMock = jest.fn()
T.qd.sync = syncMock
@@ -122,8 +122,18 @@ describe('Textbox.tsx', () => {
expect(syncMock).not.toBeCalled()
})
- it('Does not call sync on enter - multiline is true', () => {
- const { getByTestId } = render()
+ it('Does not call sync on enter pressed - submit not specified', () => {
+ const { getByTestId } = render()
+ const syncMock = jest.fn()
+
+ T.qd.sync = syncMock
+ fireEvent.keyUp(getByTestId(name), { key: 'Enter', target: { value: 'text' } })
+
+ expect(syncMock).not.toBeCalled()
+ })
+
+ it('Does not call sync on enter - multiline and submit both are true', () => {
+ const { getByTestId } = render()
const syncMock = jest.fn()
T.qd.sync = syncMock
diff --git a/ui/src/textbox.tsx b/ui/src/textbox.tsx
index 7d9c5644c6a..fa0e796df53 100644
--- a/ui/src/textbox.tsx
+++ b/ui/src/textbox.tsx
@@ -62,6 +62,8 @@ export interface Textbox {
visible?: B
/** An optional tooltip message displayed when a user clicks the help icon to the right of the component. */
tooltip?: S
+ /** True if the form should be submitted when enter key is pressed. */
+ submit?: B
}
const DEBOUNCE_TIMEOUT = 500
@@ -95,7 +97,7 @@ export const
disabled={m.disabled}
readOnly={m.readonly}
onChange={m.trigger ? debounce(DEBOUNCE_TIMEOUT, onChange) : onChange}
- onKeyUp={onKeyUp}
+ onKeyUp={m.submit ? onKeyUp: undefined}
/>
)
: (
@@ -116,7 +118,7 @@ export const
multiline={m.multiline}
type={m.password ? 'password' : undefined}
onChange={m.trigger ? debounce(DEBOUNCE_TIMEOUT, onChange) : onChange}
- onKeyUp={onKeyUp}
+ onKeyUp={m.submit ? onKeyUp: undefined}
/>
)