Fork me on GitHub
#reagent
<
2015-07-28
>
colin.yates00:07:06

@ulsa I find https://github.com/Prismatic/dommy useful, usually as an on-ramp to seeing how to use the underlying Google Closure library

curtosis16:07:37

I'm trying to make a button change text based on an atom. anyone have a simple example I can look at?

gadfly36116:07:46

All you should need is to deref the atom (make sure it is a reagent atom, I have been bit by this a few times). This isnt exactly what you asked, but could be useful: https://github.com/reagent-project/reagent-cookbook/blob/master/recipes/toggle-class/README.md

curtosis16:07:02

thanks... I think I probably have something just crossed up in my head.

gadfly36116:07:10

The class is updated on change of atom with a deref. You can do somethinf similar and store the text in the atom and then deref in the spot for the buttons text.

curtosis16:07:42

well, my first problem was not calling my new subcomponent button facepalm

curtosis16:07:46

but now it's not updating when the atom changes.... in the (sub)component I'm doing (if (@state :in-progress) "Foo" "Bar"). Does that not bypass the change propagation? (still learning how reagent is wired together..)

curtosis16:07:47

or is it only possible to set the button text in the state atom?

curtosis16:07:19

actually, that doesn't solve it either. rats.

coyotespike16:07:52

I've been changing out buttons, which might look the same but have different text.

curtosis16:07:25

that's what I'm trying now

coyotespike16:07:22

(defn one-button [showme]
  (fn []
     [:input {:class "btn btn-info palette-turquoise"
              :type "button"
              :on-click #(.-preventDefault (swap! showme not))}]))
(defn switch-buttons [atom default alternative]
  (fn []
    (if @atom
      default
      alternative)))

(def my-page []
  (let [showme (atom true)]
[switch-buttons showme [one-button showme] [other-button]]))

coyotespike16:07:49

Along those lines, possibly inelegant but hey.

curtosis16:07:32

This is what is now (I think) working:

(defn analyze-button []
  [:button {:on-click nil} (if (@state :analyzing) "Analyzing..." "Analyze!")])

curtosis16:07:56

:on-click to be added, obviously simple_smile

curtosis16:07:25

what I actually want is a progress spinner, but baby steps.

coyotespike16:07:47

Ah, interesting, I'll play around with this way of doing it ... progress spinner would be sweet 😎

gadfly36116:07:02

For the on-click

gadfly36116:07:49

#(if (= @state :text) "foo") (swap! state assoc :text "bar") (swap! state assoc :text "foo"))

gadfly36116:07:32

Assuming (def state (reagent/atom {:text "foo"})

gadfly36116:07:49

Just tested it, will update button text

curtosis16:07:33

my on-click actually needs to kick off the analysis call. Now it's irritating that I have to put (if (@state :analyzing) ...) in 3 places in the button component. capturing it in a let blocks the update propagation, sort of expectedly.

gadfly36116:07:54

You can pull out the deref to the top

gadfly36116:07:08

Make a button component and pass in the deref as an argument to the button

gadfly36116:07:31

Since the deref happens above the button component, it will rerender whole thing when atom changes

gadfly36116:07:01

So then you can get rid of all the derefa in the button

curtosis17:07:38

aaah... so something like:

(defn analyze-button [analyzing?]
    [:button (if analyzing? "foo" "bar")])
and call it like:
[analyze-button (@state :analyzing?)]
?

curtosis17:07:07

hmm... that didn't work.

curtosis17:07:12

nvm... it does. had an error somewhere that got missed in the figwheeling.

curtosis17:07:38

grr. weirdness.

curtosis17:07:09

so if I call (swap! state assoc :analyzing? true) in my on-click function, it works (changes the atom) but the updates don't propagate.

lazy-lambda17:07:50

Just finished the re-frame ReadMe. It was very much enlightening.

lazy-lambda17:07:02

One of the best reads of this year.

curtosis17:07:48

actually, now it's not working at all again. aaaaaaaaugh.

curtosis17:07:26

could this be some weird interation with reagent-forms/bind-fields ?

curtosis17:07:47

This is the whole thing:

(defn do-analyze []
  (swap! state assoc :analyzing? true)
  (println "Analyzing!"))

(defn analyze-button [analyzing?]
  [:button {:on-click do-analyze 
            :class (when analyzing? "disabled") 
            :disabled analyzing?}
   (if analyzing? "Analyzing..." "Analyze!")])

(def note-form-template
  [:div.row
   [:textarea {:field :textarea
               :id :note-text}]
   [:br]
   [analyze-button (@state :analyzing?)]])

(defn clinical-note-form []
  [:div
   [bind-fields clinical-note-form-template state]])

curtosis17:07:46

setting it from the figwheel repl doesn't propagate now either. no idea what's going on.

curtosis17:07:56

I swear it worked moments ago!

svileng17:07:57

Hey everyone — is this a good place to ask for help? I wrote about 15 lines of cljs/reagent and can't figure out why the value of an atom is not showing in the UI.

gadfly36117:07:13

This is a good place to ask questions! (Sometimes questions get buried in convos, so just re-ask if your thread gets lost). Im away from keyboard for a while or id try to help out too.

svileng17:07:15

Here it is:

1 (ns cljs.todos.core)
  2
  3 (def new-todo (atom {:text ""}))
  4
  5 (defn- update-new-todo [event]
  6   ;;(.log js/console (.-target.value event))
  7   (swap! new-todo assoc :text (.-target.value event))
  8   (.log js/console (str "New todo value: " (:text @new-todo))))
  9
 10 (defn add-todo [todos]
 11   [:div
 12     [:textarea {:cols "35" :rows "5" :on-change update-new-todo}]
 13     [:div
 14       [:button {:on-click #(swap! todos conj @new-todo)} "Add to list"]]
 15     [:p (str "Preview: " (:text @new-todo))]])
I can see that the new-todo atom gets updated, but line 15 isn't showing the value for some reason!

gadfly36117:07:34

At first glance, need to use a reagent atom

svileng17:07:22

thanks for spotting it @gadfly361! That must be it!!

svileng17:07:47

yep, fixed! 😊

curtosis18:07:13

well, ripping it completely out of reagent-forms seems to be making things better.

curtosis18:07:40

there must be some weird derefa interactions I don't yet grok.

jeffmk18:07:22

It seems to be a common problem. I wonder if shadowing atom instead of using something like radom causes more bugs than adds convenience.

curtosis18:07:48

I explicitly namespace it, usually to r/atom, for that reason.

curtosis19:07:34

(I say that like I have a working reagent app or something. ;-))

jeffmk19:07:36

Right, the problem is it seems like documentation invites you to just map it over atom. I too was thinking of using r/atom instead.

lazy-lambda19:07:59

Can re-frame handler have side-effects ?

danielcompton21:07:39

@lazy-lambda: yep, that's where they're all meant to live

danielcompton21:07:29

@gadfly361: is it worth logging a warning if the user tries to do reagent things with an atom instead of a ratom?

gadfly36121:07:51

Hmm I could see arguments for both sides. That's a good question for Dan (dont think he is on slack yet).

gadfly36123:07:30

@curtosis @jeffmk @danielcompton I agree and never use :refer [atom] in a namespace. Actually, I never refer anything from any library bc I think it makes you squint when remembering where it's from (but that is more of a preference .. clarity > brevity)

jeffmk23:07:52

@gadfly361: Same. I find a one- or two-char namespace alias works well for deobfuscation without adding too much clutter.

curtosis23:07:42

the only ones I think unambigously make sense to :refer are from core.async. that seems idiomatic. otherwise, it's a trap. I still do it sometimes, but I know it's a trap that may bite me later.