Fork me on GitHub
#clojurescript
<
2023-01-22
>
hifumi12306:01:20

Has anyone here used Keycloakify with reagent? Would it be too tedious to do so? Asking before sunk cost hits me 😄 EDIT: Decided to risk it and so far it seems to work!

M J13:01:38

Hello, I am working on an email input component, with email validation, and want a delay for the email validation. That means, as long as the user is typing, not to show that email is invalid, and only after 3 seconds after the last letter was typed, to call the email-validation fn. MY end goal is that I dont want to show the user the error message as long as he is typing. The problem is, the "clear-delay-id" does not clear, and when it prints for each input, not just the last one like I want. This is what I have

(defn on-change-action [text-val value field button-disabled? email-valid? delay-validation]
  (let [timeout-id (js/setTimeout (fn []
                                    (when @button-disabled? ((reset! email-valid? false)
                                                             (prn "invalid email")))) 3000)
        clear-delay-id (js/clearTimeout timeout-id)]
    (reset! text-val value)
 
    (if (validate-email value)
      ((clear-delay-id)
       (reset! email-valid? true)
       (reset! button-disabled? false))

      (timeout-id
       (reset! button-disabled? true)))

p-himik14:01:29

((reset! email-valid? false)
 (prn "invalid email"))
This part will call false as a function on the result of (prn ...) - a nil. The reset and the printing will be done but you should see an exception in the JS console. To fix it, just remove the outermost parens. Another problem is that you call js/clearTimeout immediately. That JS function, as its name suggests, immediately clears the timeout, without waiting. So in effect, your code schedules a reset and then immediately cancels that schedule. Also, timeout-id and clear-delay-id are not functions. They are IDs.

p-himik14:01:30

A note on UX - I would reduce 3 seconds down to 0.5 or at least 1 second. The vast majority of people type their own email much faster than one character every second. (citation needed)

M J14:01:36

I dont understand what I should change. the printing of "invalid email" is done with each type. There is a delay, but it does not cancel the last one. For instance, if I type "p-himik": I want only 1 PRINT, 3 seconds after typing the "k" Right now, it prints 7 times, once for each letter

p-himik14:01:08

Are you sure that your web page is running the same exact code and not some cached previous version of it? Because the code that you posted should fail loudly, with an exception in the JS console.

M J14:01:56

Yes, it shows errors, but its working

p-himik15:01:08

Those two statements contradict each other. The code above will: 1. Schedule a function call to happen 3 seconds later 2. Immediately cancel that schedule 3. Reset text-val to a new value 4. Validate the value 5. Fail regardless of the validation result because timeout-id is an integer and clear-delay-id is nil and neither of them are callable

p-himik15:01:55

Perhaps you print out "invalid email" in some other location as well. Apart from that, there's little I can do without the full code.

M J15:01:22

Yes Im sure. I made some changes, but still I want the delay to only start when last input is typed, not every input:

(defn on-change-action [text-val value field button-disabled? email-valid? delay-validation]
  (let [timeout-id (js/setTimeout (fn []
                                    (when @button-disabled? (reset! email-valid? false)
                                          (println "invalid email"))) 3000)]
    (reset! text-val value)
    
    (if (validate-email value)
      ((js/clearTimeout timeout-id)
       (reset! email-valid? true)
       (reset! button-disabled? false))

      (timeout-id 
       (reset! button-disabled? true)))

p-himik15:01:58

() is not for grouping, it's for creating lists, most often in the context of calling a function or a macro (i.e. (f a b) would call function f on arguments a and b). So that ((js/clearTimeout timeout-id) ... is incorrect. And check out the documentation for clearTimeout and setTimeout, specifically for their return values and for usage examples. Of course, the examples will be in JS, but they're usually rather easy to understand. Given your other question, I would definitely suggest first learning Clojure[Script] by using some specific resources for learning instead of trying to write a full-on app.

M J14:01:06

If I want to remove the # from on-change, how do I target the (-> % .-target .-value) in another way (snce I need the %):

[text-field {:variant "filled"
                                              :max-rows 1
                                              :model          @text-val
                                              :on-change #(on-change-action text-val (-> % .-target .-value) field button-disabled? email-valid?)
                                              :on-blur #(on-blur-action)}]

p-himik14:01:05

#( ... % ...) is syntax sugar for (fn [x] ... x ...). Of course, x can have any other name - it's just an argument.

M J15:01:06

CAn you please write exactly how I would go about doing that as fn as Im not succeeding

#(on-change-action text-val (-> % .-target .-value) field button-disabled? email-valid? delay-validation)

p-himik15:01:36

(fn [x]
  (on-change-action text-val (-> x .-target .-value) field button-disabled? email-valid? delay-validation))
I suggest to stop by #C053AK3F9 - that channel is specifically for questions like this one.

🙌 2
M J16:01:18

Ok np. Thanks alot btw this helped fix the problem

👍 2