Clojurians
#re-frame
<
2018-07-16
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

arne-clojurians07:07:12

hi! is there any example of using https://github.com/ptaoussanis/tempura w/ re-frame? i was thinking about using subscriptions to get the correct translations for the current user but i don't want all of my views to become impure by depending on subscriptions, but i'd also like to avoid passing arguments far down the chain. any idea?

nenadalm17:07:51

Hi. I have tr function which I then call wherever I want in the app:

(ns 
  (:require
   [taoensso.tempura :as tempura]
   [app.messages :refer [messages]]))

(defn- missing-resource-fn [{:keys [resource-ids]}]
  (subs (str (first resource-ids)) 1))

(defn tr [& rest]
  (apply tempura/tr
         {:dict messages
          :missing-resource-fn missing-resource-fn}
         [:cs]
         rest))
so in some component, I just call it like:
[ui/DialogContentText
     (tr [:app.list.file.delete_confirmation/body]]

valtteri07:07:10

Hi, I struggled with the same question a while ago and ended up passing args down the chain

valtteri07:07:48

Not with Tempura though but https://github.com/tonsky/tongue which is very similar

valtteri07:07:23

However, I’m pretty new to re-frame and not yet very confident deciding when to use subscriptions vs passing props/args. In the beginning I tended to pass more args down the chain but now I feel that subscriptions are actually really nice in many situations. It depends.

arne-clojurians09:07:25

hm.. giving it a little thought, maybe subscriptions aren't so bad? i mean impurity would only be a problem for me if it makes things less predictable / testable, but there is this approach here: https://github.com/Day8/re-frame/blob/master/docs/Testing.md#view-functions---part-2b

arne-clojurians09:07:39

of course it would be nicer to do avoid impurity, but i18n will be necessarily sprinkled all over the app and i don't see an easy way out at the moment. if anybody has any more input i'm all ears

p-himik09:07:31

@arne-clojurians There were some efforts to create a pure version of re-frame. E.g. https://github.com/binaryage/pure-frame Some discussion is here https://github.com/Day8/re-frame/issues/137. There's also interesting info available by the links in that issue.

p-himik09:07:34

Oh, there's even #pure-frame

aaron99311:07:31

Hi all, glad I found this channel!

mikethompson11:07:39

@p-himik @arne-clojurians and further (incomplete) exploration here https://github.com/Day8/re-frame/blob/master/docs/EPs/002-ReframeInstances.md

aaron99311:07:28

I have a table that is populated with data from Firestore. What I am trying to achieve is to have an edit button after each row, and when that is clicked have the fields in that row become editable text fields. What I am struggling with is getting that change to occur. Here is what I have so far:

(defn device-row [device]
  (let [edit-mode?      (reagent/atom false)
        text-val        (reagent/atom "")
        status          (reagent/atom nil)
        status-tooltip  (reagent/atom "")

        ]
    [h-box
     :class "rc-div-table-row"
     :width "1060px"
     :gap "15px"
     :children [              ;;use to bump columns to the right
                [box :size "initial" :width "1px" :child [title :label ""]]
                [box :size "initial" :width "160px"
                 :child [p (get device "deviceName" "Default Value")]]
                [box :size "initial" :width "100px"
                 :child [p (get device "owned" "Default Value")]]
                [gap :size "17px"] ;; required to accomodate Owned? sorting buttons
                [box :size "initial" :width "115px"
                 :child [p (get device "ownedBy" "Not Owned")]]
                [box :size "initial" :width "185px"
                 :child [p (get device "initialStateLink" "Default Value")]]
                [box :size "initial" :width "180px"
                 :child [p (get device "number" "Default Value")]]
                [box :size "initial" :width "170px"
                 :child [p (get device "assignedDate" "Default Value")]]
                [md-icon-button :md-icon-name "zmdi zmdi-edit"
                 :on-click #(do (reset! edit-mode? true)
                                (println "Trying to turn on edit mode"))];;;;;;add on-click
                (when @edit-mode? [h-box
                               :children [[box :size "initial" :width "1px" :child [title :label ""]]
                                          [box :size "initial" :width "160px"
                                           :child [p (get device "deviceName" "Default Value")]]
                                          [input-text
                                           :model text-val
                                           :on-change #(reset! text-val %)
                                           :width "100px"
                                           :height "20px"
                                           :placeholder "Hello"
                        , meet with rachel                   ]
                                          [gap :size "17px"] ;; required to accomodate Owned? sorting buttons
                                          [box :size "initial" :width "115px"
                                           :child [p (get device "ownedBy" "Not Owned")]]
                                          [box :size "initial" :width "185px"
                                           :child [p (get device "initialStateLink" "Default Value")]]
                                          [box :size "initial" :width "180px"
                                           :child [p (get device "number" "Default Value")]]
                                          [box :size "initial" :width "170px"
                                           :child [p (get device "assignedDate" "Default Value")]]
                                          [md-icon-button :md-icon-name "zmdi zmdi-edit"
                                           :on-click #(reset! edit-mode? false)]
                                          ]])]]))

aaron99311:07:17

Excuse the ugly css column widths in there... Does anyone have any suggestions?

aaron99311:07:41

I am using an "edit-mode?" atom to try to trigger the change

manutter5111:07:57

What’s the behavior you’re seeing now, and how is that different from what you want to see?

p-himik11:07:18

@aaron993 You have atoms defined inside the Form-1 component, so they're recreated each time the component is rerendered. You either have to create a Form-2 component, or use subscriptions.

aaron99311:07:42

Good question: When clicking the edit button, the loggin "Trying to turn on edit mode" works, but nothing new renders

mikethompson11:07:12

@aaronmmartz that's a Form-1 component. So when it rerenders, the reagent/atoms will be destroyed and recreated losing whatever previous value they had.

aaron99311:07:21

Ahh! So the second layout would be a Form-2 component?

aaron99311:07:37

Do oyu guys have a link to reading to change that?

aaron99311:07:12

Awesome, thanks for the direction to head

aaron99311:07:04

Thanks, that is what Iwas looking for

b2berry20:07:56

Hmm so I’ve got a case where a user fills out a short form, at the end of it, I want to set focus back to a specific field so additional entry can take place. to be tidy I think I’d use reg-event-fx and set focus via a side effect?

manutter5120:07:34

That should work as long as the field you’re trying to set the focus on does not re-render in the meantime

manutter5120:07:35

Otherwise you can set a value in the app-db, and have your target field call focus on itself during :component-did-update

b2berry20:07:34

Yeah I considered that, too, it’s sometimes a little tedious to drive every ounce of behavior by something in the app-db. Is there a time and place for calling something like a focus-on function that sets the focus directly?

b2berry20:07:37

Is that a cardinal sin? I can find a place in my app-db model to drive it by data. I’m sorta just trying to calibrate my mental model here on which it’s OK to be explicit about setting behavior in the DOM vs “data all the things”

manutter5120:07:44

I’d try it without the app-db first, but just be aware of the “lost focus because component re-rendered” gotcha. If it re-renders and drops focus as soon as you set it, then go ahead and set the flag in the db (or wherever)

gmercer21:07:08

Hi, I'm using the :active-panel pattern from the docs, but after the change to panel2 it shows for millis and then the app does a full reload (browser console says "Navigated to http://localhost:10555/" which is the same message I would get after refreshing browser). If I swap! to toggle the panels via the repl the views toggle perfectly. I even created a new chestnut and re-implemented activepanel and do not get the page reload. Obviously, I have introduced a subtle difference. I am just looking for a technique to find the trigger that is forcing the reload.

manutter5122:07:50

@gmercer Is this in an :on-click handler? If so you might try returning false from the handler explicitly, or calling .preventDefault on the event that gets passed in to your handler.

gmercer22:07:44

Yes, an :on-click handler, I will try those .. gimme a tick

gmercer22:07:12

It is a simple dispatch {:on-click #(dispatch [:signup/navigate])}

gmercer22:07:15

@ changing from :on-click #(dispatch [:signup/navigate]) to :on-click (fn [e] (.preventDefault e) (dispatch [:signup/navigate])) stopped the reload

gmercer22:07:36

@ but why? .. do I need to do this everywhere ?

manutter5122:07:36

The default action on anchors is to change the page location, triggering a reload

manutter5122:07:52

If you use something besides an a tag, you won’t have this problem.

gmercer22:07:17

it is a button

manutter5122:07:37

button as in a [:button ...] tag?

gmercer22:07:48

I think I might chuck that handler function from the doco above and sprinkle in a preventDefault

gmercer22:07:32

[:button.btn.btn-info.btn-xs.offset-md-1 {:on-click (fn [e] (.preventDefault e) (dispatch [:signup/navigate]))} "Create one now!"]

manutter5122:07:38

I would probably make a utility function somewhere like

(defn mk-click-handler [event-vec]
  (fn [e] 
    (.preventDefault e)
    (dispatch event-vec)))

manutter5122:07:20

then do

[:button {:on-click (mk-click-handler [:signup/navigate])}]

manutter5122:07:16

so you get that handy one-line :on-click line, and the .preventDefault built in

gmercer22:07:09

`(defmacro handler-fn ([& body] (fn [~'event] [email protected] nil))) is the suggestion on the page, so `(defmacro handler-fn ([& body] (fn [~'event] (.preventDefault event) [email protected] nil))) would be the upgrade ;)

manutter5122:07:43

Hmm, a macro seems like overkill to me, unless you’re going to need to do something really heavy duty in the body

manutter5122:07:34

Personally I think an :on-click handler should do the bare minimum, dispatch an event and maybe call .preventDefault if you need it.

manutter5122:07:44

and an ordinary fn is sufficient for that.

gmercer22:07:19

I still have a burning need to know why it is needed at all ...

manutter5122:07:48

Is your button inside a [:form ...] tag?

gmercer22:07:40

yes, [:form {:role "form"} ...

manutter5122:07:39

That’s why then. The browser is saying, “Oh, you’re clicking a button in the form, you must want to submit the form.”

manutter5122:07:43

That’s my guess anyway.

manutter5122:07:21

When you click the button, the browser “submits” the form data, expecting the server to send back a result page

manutter5122:07:40

In this case, the server sends back the same page, so you get the reload effect.

gmercer22:07:45

cool, forms begone .. I will rely on events/subs

manutter5122:07:36

If you’re handling sending the form data to the server directly, via AJAX calls, then you don’t need the [:form...] tag, and getting rid of it will remove that default behavior

gmercer22:07:10

Thank you so much

aaron99322:07:40

Hi all, I messaged earlier about about a problem and was directed to use a Form-2 instead of a Form-1. I am trying that, and now that I added a fn[] to my function, the view is not being rendered. Any suggestions? Is this a common problem?

aaron99322:07:52

` (defn device-row [device] (let [edit-mode? (reagent/atom false) text-val (reagent/atom "") status (reagent/atom nil) status-tooltip (reagent/atom "") ] (fn [device] [h-box :class "rc-div-table-row" :width "1060px" :gap "15px" :children [ ;;use to bump columns to the right [box :size "initial" :width "1px" :child [title :label ""]] [box :size "initial" :width "160px" :child [p (get device "deviceName" "Default Value")]] [box :size "initial" :width "100px" :child [p (get device "owned" "Default Value")]] [gap :size "17px"] ;; required to accomodate Owned? sorting buttons [box :size "initial" :width "115px" :child [p (get device "ownedBy" "Not Owned")]] [box :size "initial" :width "185px" :child [p (get device "initialStateLink" "Default Value")]] [box :size "initial" :width "180px" :child [p (get device "number" "Default Value")]] [box :size "initial" :width "170px" :child [p (get device "assignedDate" "Default Value")]] [md-icon-button :md-icon-name "zmdi zmdi-edit" :on-click #(do (reset! edit-mode? true) (println "Trying to turn on edit mode"))] (when @edit-mode? [h-box :children [ ;;use to bump columns to the right [box :size "initial" :width "1px" :child [title :label ""]] [box :size "initial" :width "160px" :child [p (get device "deviceName" "Default Value")]] [box :size "initial" :width "100px" :child [p (get device "owned" "Default Value")]] [gap :size "17px"] ;; required to accomodate Owned? sorting buttons [box :size "initial" :width "115px" :child [p (get device "ownedBy" "Not Owned")]] [box :size "initial" :width "185px" :child [p (get device "initialStateLink" "Default Value")]] [box :size "initial" :width "180px" :child [p (get device "number" "Default Value")]] [box :size "initial" :width "170px" :child [p (get device "assignedDate" "Default Value")]] [md-icon-button :md-icon-name "zmdi zmdi-edit" :on-click #(do (reset! edit-mode? true) (println "Trying to turn on edit mode"))] ]])] ])))

aaron99322:07:08

Probably I messed up the code somewhere, but I can't figure out where