From 3e9960f9d16110cd78082cff4758b6f91296c1b5 Mon Sep 17 00:00:00 2001 From: Falko Schindler Date: Fri, 20 Jan 2023 18:55:52 +0100 Subject: [PATCH] #271 introduce password toggle button for ui.input --- nicegui/elements/input.py | 13 ++++++++++++- tests/test_input.py | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/nicegui/elements/input.py b/nicegui/elements/input.py index 85ed52c1a..a8dc5947a 100644 --- a/nicegui/elements/input.py +++ b/nicegui/elements/input.py @@ -1,5 +1,6 @@ from typing import Callable, Optional +from .icon import Icon from .mixins.value_element import ValueElement @@ -10,16 +11,26 @@ def __init__(self, placeholder: Optional[str] = None, value: str = '', password: bool = False, + password_toggle_button: bool = False, on_change: Optional[Callable] = None) -> None: """Text Input :param label: displayed label for the text input :param placeholder: text to show if no value is entered :param value: the current value of the text input - :param password: whether to hide the input + :param password: whether to hide the input (default: False) + :param password_toggle_button: whether to show a button to toggle the password visibility (default: False) :param on_change: callback to execute when the input is confirmed by leaving the focus """ super().__init__(tag='q-input', value=value, on_value_change=on_change) self._props['label'] = label self._props['placeholder'] = placeholder self._props['type'] = 'password' if password else 'text' + + if password_toggle_button: + with self.add_slot('append'): + def toggle_type(_): + is_hidden = self._props.get('type') == 'password' + icon.props(f'name={"visibility" if is_hidden else "visibility_off"}') + self.props(f'type={"text" if is_hidden else "password"}') + icon = Icon('visibility_off').classes('cursor-pointer').on('click', toggle_type) diff --git a/tests/test_input.py b/tests/test_input.py index 61cbfcb78..91aa87d05 100644 --- a/tests/test_input.py +++ b/tests/test_input.py @@ -30,3 +30,21 @@ def test_password(screen: Screen): element.send_keys('789') assert element.get_attribute('value') == '123456789' + + +def test_toggle_button(screen: Screen): + ui.input('Your password', value='123456', password=True, password_toggle_button=True) + + screen.open('/') + screen.should_contain('Your password') + screen.should_contain('visibility_off') + + element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Your password"]') + assert element.get_attribute('type') == 'password' + assert element.get_attribute('value') == '123456' + + screen.click('visibility_off') + assert element.get_attribute('type') == 'text' + + screen.click('visibility') + assert element.get_attribute('type') == 'password'