Fork me on GitHub
#humbleui
<
2023-03-17
>
Quest19:03:28

In response to a bug I found, I'm considering how to write a library option to enable the behavior of "text-input ignoring certain keys." My exact case is that I want to input text, then press Enter to 'submit' (clear text + invoke a function.) The library currently invokes the parent :enter callback but also adds an empty newline/enter character to the end of the :text string, which triggers a UI re-update (and an exception in my bugged case.) Here's the options I'm considering, & does anyone have any advice or thoughts before I start implementation? ----------------- A) Implement preventDefault (ala Elm) as a supported option for the TextInput class. This would take a seq of keyword 'keys' that should be ignored. B) Option A might be better implemented as the ability to stop further event propagation as it's "captured" from the parent to child elements? Then a wrapping focusable or on-key-focused could handle this. C) Ignore A/B, extend :on-change as suggested by Lilactown's example in https://github.com/HumbleUI/HumbleUI/issues/68

(let [*num (atom {:text "23"})]
  (ui/text-field
    {:on-change #(when (Float/parseFloat %) (swap! *num assoc :text %))}
    *num))
This would hypothetically allow :on-change to override the text-input's default behavior and control all set text. It will require some good refactor, as the current draft impl only invokes :on-change as a side-effect.

Niki12:03:58

Take a look at ui/on-key-focused The way it works is that if your callback returns truth-y value, the event propagation stops and child never receives it

Quest17:03:43

Returning nil fixed my UI with just a few characters. Thanks & I'll comb through the src a little more this week 👀

Quest18:03:48

I'm tracking down a bug where events are propagating down to the text-input class even when a higher level :enter handler returns nil on the :enter key-event. In the worst case, :text still gets updated to include a \r at the end, but the :line value gets nil'd and the UI library crashes. It might be that triggering another update to the state during the key-event is causing this, or perhaps from blocking the UI thread for too long. LMK if you have any pointers on this but otherwise I'll keep going until I can PR a fix

Niki19:03:32

All event handlers happen on UI thread, there’s now way to hold it for too long

Niki19:03:56

I’ll take a look if yoy can open an issue

👍 2
Quest19:03:11

Sure, I'll try to nail down a more exact repro if I can't figure it out myself. There was one other edge -- text-input doesn't seem to work inside of a ui/dynamic block. Higher level focusable will still trigger a (mouse click) callback, but text-input doesn't respond to any key-events. I haven't gone digging yet but we'll see

Niki19:03:03

that’s probably focus issue because text field is recreated by dynamic. I still have to figure it out

Niki19:03:57

Try creating text input outside

Quest19:03:21

It does work outside -- did a few repros with the only difference being the wrapping dynamic. It's almost certainly the cause

Quest19:03:45

I'm interested in rewriting these to play nice together. Have any notes you'd want to bring up?

Niki19:03:53

I wish it was so simple. I’m afraid to solve this properly you’ll need to replace dynamic with smth better

2
Niki19:03:48

There might be an easier fix right now, probably in focus-controller somewhere. I bet your issue is that text-field loses focus

Niki19:03:27

What I meant: try creating it outside (as a value) but then use that value inside dynamic

💯 2
Niki19:03:37

I understand it won’t always work

Niki19:03:50

But might be possible in your case

Quest20:03:37

Your theory is correct from tests -- creating text-field in a let above the dynamic, & then using it inside dynamic works. I see this is already open at Text field inside of dynamic loses focus when re-rendered - https://github.com/HumbleUI/HumbleUI/issues/50 I originally tried using dynamic for a wrapping router component on the state's :main-screen value. This is a nice pattern that I don't want to giveup, so I'll go looking for the simple fix you alluded to (storing text-field focus in the atom) You mention eventually replacing dynamic with something more reliable. I understand if you're too busy for a writeup, but I'd love to know your thoughts here in case I need to try & implement this

Quest01:03:05

Found some success adding key :focused to the :text-input state & having it set :focused of its wrapping Focusable component. Thanks for the clues -- code appears to work but has some awkward parts. I'll refactor & test more tomorrow

👍 2
Quest20:03:09

Opened https://github.com/HumbleUI/HumbleUI/pull/71 . My initial commit breaks parent on-key-focus callbacks though, might be a better way to do this