Fork me on GitHub
#re-frame
<
2018-01-26
>
mikerod00:01:58

I moved my comments to a thread since I didn’t mean to spam this man channel - Sorry if that was confusing.

stvnmllr203:01:45

If anyone knows how to force a component with local state to reload from scratch, it might save me a bunch of time. any takers?

stvnmllr203:01:05

(defn text-area [{:keys [path default-value id] :as props}]
  (let [value (r/atom (if default-value default-value ""))]
    (r/create-class 
      {:display-name "text-area"
       :component-did-mount
       (fn text-area-did-mount [this]
         (js/autosize (r/dom-node this)))
       :reagent-render
       (fn text-area-render [{:keys [path default-value id] :as props}]
         [:textarea.form-control.autosizing
          (merge (dissoc props :path) 
                 (addid 
                   id 
                   {:value       @value
                    :on-change   #(reset! value (-> % .-target .-value))
                    :on-blur #(rf/dispatch [:update-value path @value])}))])})))

stvnmllr204:01:35

Seems there is no way to change the state inside a component from outside. So... will try another way. cheers 🍺

stvnmllr204:01:05

I did get it to work by hiding the component, then enabling it later, but that was pretty hacky

danielcompton05:01:30

On mobile so can’t get the full context from the code, but a hack is to change the ^{:key for a component to force it to be created

danielcompton09:01:32

re-frame-trace 0.1.16 is out https://github.com/Day8/re-frame-trace/releases/tag/0.1.16. Now with React 16 and Reagent 0.8.0 support

manuel09:01:04

@danielcompton thanks, it removed the React.createClass is deprecated and will be removed in version 16 warning from my console

manuel09:01:45

I upgraded reagent to 0.8.0-alpha2 as well, and everything is working fine.

hkjels09:01:48

@danielcompton I just upgraded re-frame-trace on a project where I’m using [garden "2.0.0-alpha1"]. It seems that my version of garden takes presidence, but it’s API is not compatible. Do you know of a quick-fix?

danielcompton05:01:18

I've pushed out a release bundling Garden source dependencies in 0.1.17-20180127.054500-1, can you give it a go and let me know how you get on?

hkjels17:02:43

Hi, I’m sorry for the late feedback ;( Unfortunately, it did not solve the issue completely, it failed at another fn

hkjels09:01:01

Invalid :refer, var garden.compiler/render-css does not exist

hkjels09:01:56

It doesn’t seem like the correct behavior by ClojureScript. Versions are pinned, so both should be running side-by-side

joshkh11:01:06

just wrapping my head around the undo fx: if a dependency of my project also uses undo and it mutates the config with custom harvesters, those configurations leak into the parent app, right? https://github.com/Day8/re-frame-undo

Stefan Roex13:01:01

Hi! I'm trying to figure out how a subscription in re-frame works. Maybe some can help me? I've always believed that calling (subscribe [:something]) returned something which is exactly the same as a reagent reaction. However, I when I deref a subscribe in a reagent run! macro, the body isn't rerun when the subscribed data changes...

Stefan Roex13:01:31

This does work however when I replace subscribe with a reaction. For example (reaction (::db/cart @re.frame.db/app-db)). I cannot figure out why this is different...

pablore16:01:42

Hello, I’m trying to learn re-frame to upgrade my cljs apps. Are there any resources/tutorials/books out there that may help me?

danielcompton20:01:33

@U7V9HE682 there's tons of docs as well in the re-frame repo

kenny18:01:42

@stex subscribe does return a reagent reaction. The reaction is created when you call reg-sub. See here: https://github.com/Day8/re-frame/blob/master/src/re_frame/subs.cljc#L327

Stefan Roex18:01:46

@kenny Thanks! The puzzeling thing is that a subscribe doesn't work in a run! macro, which is essentially just a reaction which auto-runs.

danielcompton20:01:11

@hkjels https://clojurians.slack.com/archives/C073DKH9P/p1516959476000169 You can only run one version of a library at a time, Leiningen/Boot will only pick one if there are multiple different versions required

rgm21:01:26

hi gang ... hoping someone could point me to a tutorial on file downloads (alternately, tell me that I'm fundamentally misconceiving this problem):

rgm21:01:04

I have client-side state that I want to render as an Excel file, and js-xlsx isn't going to cut it, so I'm wanting to use docjure.

rgm21:01:19

which is server-side Java.

rgm21:01:57

my current experiment, summarized: user hits "download as excel" button. This dispatches a please-download event. Event is caught by fx handler.

rgm21:01:39

fx handler sets a "downloading" flag in app-db for UI feedback, and dispatches an http-xhrio POST with the browser-side data from the app-db.

rgm21:01:34

a ring handler picks up the POST data, does what it needs to do to make up an Excel file, and ...

rgm21:01:23

so here's where I go off the rails. I've tested giving back a text file in the xhrio success handler with the Content-Disposition header set to attachment but that's almost certainly not what I want and I've run smack into the joy that is dealing with file writes in a browser.

rgm21:01:20

so I can log the text file contents (ie. cljs-ajax is receiving OK) in the re-frame event handler, but I'm scratching my head a bit on the right thing to google here.

danielcompton21:01:32

@rgm what exactly is the problem? i.e. what do you want to happen that isn't happening here?

danielcompton21:01:58

Sounds like you're wanting to trigger the browsers file download mechanism?

rgm21:01:03

the browser should save a file to ~/Downloads ... exactly

rgm21:01:45

Experience suggests I'm off the track here given there's no obvious re-frame doc to read.

danielcompton21:01:49

Ignoring re-frame for a second, how would you do this with JS or CLJS?

rgm21:01:33

probably just do a straight-up form POST and have the server use Content-Disposition in the response to trigger a download.

rgm21:01:12

wait ... that can't possibly work here can i... dang. I think that might.

rgm21:01:31

oh for the love of. Yep.

rgm21:01:44

that'll work, at which point re-frame's job is really just to keep a hidden input's value in sync with the app db.

rgm21:01:32

so yeah, assuming the /xlsx endpoint sends down a Content-Disposition: attachment; filename="testfile.txt" this invokes a download

rgm21:01:37

so now I'm thinking how to gracefully deal with a 500.

rgm21:01:17

since that would dump the browser's re-frame state entirely

danielcompton21:01:35

Does an XHR POST have the same effect?

rgm21:01:59

I'm .... not sure, tbh.

rgm21:01:30

you mean outside re-frame again or by arranging the xhrio effect?

danielcompton21:01:05

outside of re-frame

rgm21:01:37

just thinking how to arrange that experiment ... on-click with js interop?

danielcompton21:01:42

re-frame's role with fx is around translating stateful actions into data descriptions

danielcompton21:01:19

Doing it with cljs-ajax directly in the event handler instead of emitting the effect

rgm21:01:08

trying that.

rgm21:01:21

seems like that goes to supplying the right map to :response-format

rgm21:01:49

so that'll log server-supplied text correctly, at least.

rgm21:01:19

Content-Disposition seems not to have an effect, which also (kind of?) makes sense to me.

mikerod21:01:10

@rgm I chime in here incase it is useful. Using a side-thread to not overly spam the re-frame channel. I can’t be sure, but I think you are really wanting an xhrio (async) request/response that triggers a file download. content-disposition doesn’t work for that need since you end up needing to programmatically trigger the browser to save the file. At least, this has been my experience.

mikerod21:01:43

I have had the most luck with using the popular FileSaver.js lib (which supports a wide-range of different browser oddities) for doing programmatic client-side JS things that trigger browser file downloads.

mikerod21:01:16

I think this approach will most smoothly fit into the model of using xhrio to get the (binary) xls data back and programmatically triggering the download if that is successful vs not

mikerod21:01:59

And luckily, with FileSaver.js, there is a CLJSJS package for it already available, unless you have particular reasons you don’t want to use CLJSJS. You may be able to do some node module for it or something too, I just haven’t to give you experience on that.

mikerod21:01:24

So Basically, you end up with

(:require <etc> [cljsjs.filesaverjs] <etc>)

(defn write-xls! [xls-data filename]
  (let [blob (js/Blob. #js[xls-data]
                       ;; NOTE: I think this long thing is the mime type for xlsx
                       #js{"type" "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})]
    (js/saveAs blob filename)))

mikerod21:01:41

With something like that, you can use re-frame around all the other edges of the interchange between client-server and app state

mikerod21:01:19

I believe you could just put the write-xls! call itself in a re-frame “effect” via rf/reg-fx

rgm15:01:06

Oh nice. Thanks. I used filesaver a while back for a weird data: URL file generation scheme. 🙏

rgm15:01:06

Had kind of forgotten about it because it had some Safari limitations but looks like those have been addressed.

mikerod15:01:27

Yep. Works with safari

mikerod15:01:33

And it is a weird edge case

rgm15:01:50

At least this time it’s CLJ on the server side and I’m not doing Node acrobatics to avoid blocking the main loop during file generation.

rgm21:01:45

eh, blerg. I've got to run to a meeting.

rgm21:01:04

Greatly appreciate the help @danielcompton ... I think the short version is that I was on the wrong path and overthinking it.