nicegui icon indicating copy to clipboard operation
nicegui copied to clipboard

clearable prop error when used on ui.input()

Open Mantanium opened this issue 2 years ago • 3 comments

I tried to use the clearable prop on a ui.input(). But when clicking the x / clear button that gets added the following error gets raised:

vue.global.prod.js:1 TypeError: Cannot read properties of null (reading 'value')
    at (index):61:80
    at Proxy.map (<anonymous>)
    at (index):61:66
    at vue.global.prod.js:1:128258
    at It (vue.global.prod.js:1:13973)
    at Bt (vue.global.prod.js:1:14051)
    at sn (vue.global.prod.js:1:15956)
    at L (quasar.umd.prod.js:6:234365)
    at It (vue.global.prod.js:1:13973)
    at Bt (vue.global.prod.js:1:14051)

Example script:

from nicegui import ui

input = ui.input(label='Text', placeholder='start typing',
                 on_change=lambda e: result.set_text('you typed: ' + e.value)).props('clearable')

result = ui.label()

Is it possible to make this work without creating a custom vue component?

Mantanium avatar Jan 26 '23 20:01 Mantanium

Interesting... Thanks for reporting this issue!

Looks like the following line is a sufficient reproduction:

ui.input().props('clearable')

I'll have to investigate where exactly the problem occurs.

falkoschindler avatar Jan 26 '23 21:01 falkoschindler

I made a temporary (bulky) work around in case anyone needs this functionality before it is fixed. It changes the visibility of the X icon by color prop. Adding and removing the icon with for example visibility would resize the text input and would, in my opnion, look less clean.

from nicegui import ui


def handle_user_input(event, icon_obj):
    # Remove transparency if user input is not empty and transparency prop exists
    if event.sender.value and icon_obj._props.get('color') == 'transparent':
        icon_obj.props(remove='color=transparent')

    # Add transparency if user input is empty and transparency prop does not exists
    elif not event.sender.value and not icon_obj._props.get('color'):
        icon_obj.props(add='color=transparent')


user_input = ui.input(label='Text', placeholder='start typing', value='',
                      on_change=lambda event: handle_user_input(event, icon))

with user_input.add_slot('append'): 
    icon = ui.icon('close').props('color=transparent') \
        .on('click', lambda _: user_input.set_value(''))  # If icon is clicked clear the user input

ui.run()

ghost avatar Jan 26 '23 22:01 ghost

Quasar writes about clearable:

Appends clearable icon when a value (not undefined or null) is set; When clicked, model becomes null. https://quasar.dev/vue-components/input

It looks like this doesn't work with NiceGUI because we're not using models for our Vue elements. But maybe someone has an idea how to get it to work (apart from @Mantanium's re-implementation).

falkoschindler avatar Jan 30 '23 15:01 falkoschindler

Hey @Mantanium , I was able to make clearable work by connecting the update:model-value signal.

def on_model_value_changed(event):
    ui.notify(event.get("args"))


with ui.input(label="Username", placeholder="Enter your username") as username:
    username.props("clearable")
    username.on("update:model-value", on_model_value_changed)

Methamane avatar May 13 '23 17:05 Methamane

@Methamane Interesting...

Here is a minimized variant:

ui.input().props('clearable').on('update:model-value', lambda: None)

But you have to be careful. The value doesn't seem to change when the element is cleared:

input = ui.input().props('clearable').on('update:model-value', lambda: None)
ui.label().bind_text_from(input, 'value')

falkoschindler avatar May 17 '23 08:05 falkoschindler

Yes! @Methamane, your code snippet made me investigate the issue once more and I finally found the root cause for the problem: When using the clear button, the update:model-value event isn't an object with a value attribute, but is simply null. Yay, Quasar! My fix in 1ce5b70 handles this case and now the clearable prop simply works:

i = ui.input().props('clearable')
n = ui.number().props('clearable')
t = ui.textarea().props('clearable')

ui.label().bind_text_from(i, 'value')
ui.label().bind_text_from(n, 'value')
ui.label().bind_text_from(t, 'value')

falkoschindler avatar May 17 '23 09:05 falkoschindler

Hi @falkoschindler, Currently clearable does not "stick" with ui.number.

Using the live example at https://nicegui.io/documentation/number :

  1. Click the "x" to clear out the number
  2. Tab out or mouse click out of the number field
  3. "0" is automatically added back in

groucho86 avatar Oct 07 '23 18:10 groucho86

@groucho86 Thanks for spotting this! I created a bug report: https://github.com/zauberzeug/nicegui/issues/1765

falkoschindler avatar Oct 07 '23 19:10 falkoschindler