Fork me on GitHub
#re-frame
<
2020-12-04
>
Pavel Klavík01:12:19

Hi, can subscriptions be used inside js-event handlers, e.g. :on-click? Or should I pass their value from the component, so the handler is regenerated whenever subscription changes?

isak01:12:00

You should pass them in

p-himik05:12:44

Just in case - it's documented here but it's still not merged in. https://github.com/day8/re-frame/pull/565

alex05:12:09

Hey there! I'm using the js/File.arrayBuffer() which returns a javascript Promise, then eventually resolves with the results. When the promise resolves with results, I'd like to dispatch an API request. Any suggestions on how this should be handled in re-frame?

p-himik05:12:40

Wrap a call to dispatch in a function, pass a function to .then called on the promise.

alex05:12:36

Something similar to the below?

(defn make-api-request
  [file]
  (rf/dispatch [::make-api-request file]))


(js/File.arrayBuffer
 (.then read-file))
Would you have the arrayBuffer portion be dispatched from a separate event? The flow is user pushes button -> I need to encode the file into arrayBuffer -> then make api request

p-himik05:12:58

Yep. Make sure to also correctly handle rejection of the promise. Or at least make sure that the standard guarantees that the promise will not be rejected by the implementation.

p-himik05:12:16

> Would you have the arrayBuffer portion be dispatched from a separate event? Not sure I understand the question.

p-himik05:12:54

If I get that right, I would do everything up to the call to dispatch in the view. Saves quite a bit of a hussle.

alex05:12:10

My question was unclear but you figured it out -- thank you! Your suggestion makes sense

👍 3
Ramon Rios09:12:55

Hello. Am i able to create a re-frame event that sends a file (csv, by the way) to a browser?. I'm being able to generate the csv by event handler but don't know yet how to make it "Downloadable"

p-himik09:12:12

I don't understand what you mean. Who' the "client"? Is it the browser or the server? What does "send a file" mean in this case? Just being able to download it or to display it somehow?

Ramon Rios09:12:53

Yes, i want to click a button and download a file in my browser

lukas.rychtecky09:12:26

You have to create a element in Effect handler with attributes :href and :download and call click on the element. Something like this

(defn open-blob
  [{:keys [content filename]}]
  (let [attrs
        (clj->js {:href (-> js/window
                            .-URL
                            (.createObjectURL content))
                  :download filename})

        el (dom/createDom "a" attrs)]
    (.click el)))

p-himik09:12:46

IIRC that's not a portable solution and/or has other drawbacks that the library that I linked above tries to deal with.

lukas.rychtecky10:12:16

Sure there would be some limitations, but it could be enough solution for some cases without another dependency.

p-himik10:12:06

That dependency is just 170loc, including comments. :) I wouldn't count it as something worth the trade off.

💯 3
valtteri19:12:05

👍 for fileSaver.js. I’m also using it as a re-frame effect:

(re-frame/reg-fx
 ::save-as!
 (fn [{:keys [blob filename]}]
   (filesaver/saveAs blob filename)))

tobias22:12:11

When I send a GET request with re-frame-http-fx the namespace of the keys in the parameters is lost. For example,

{:http-xhrio {:method :get
              :uri ""
              :params {:person/id 123}
              :format (ajax/transit-request-format)
              :response-format (ajax/transit-response-format)
              :on-success [:get-person-success]
              :on-failure [:get-person-failure]}}
The request arrives at the server as {:id 123} instead of {:person/id 123}. Is this intended behaviour? If so, how do you normally work around it? Do you just design your API endpoints to use non-namespaced keywords? Or use POST instead of GET?

p-himik04:12:35

That's just how the cljs-ajax library works - it calls name on each key of the :params map of a :get request. BTW :format key is completely ignored for :get requests.

p-himik04:12:01

If you really need a namespaced parameter, you can encode it yourself, e.g. {"person/id" 123}. But you will have to make sure that your web server handles it correctly. E.g. (keyword "a/b") creates a keyword :b with the namespace a, but (keyword nil "a/b") creates a keyword :a/b with a nil namespace.

tobias06:12:02

Thanks for explaining! I just found it surprising that namespaces were dropped but if that's how it's meant to work I can deal with it. Yeah, good to know that :format is ignored for :get. I was spinning my wheels for a while trying out all the different options.

tobias11:12:26

Woah, that (keyword nil "a/b") is crazy, making the name be a/b and the namespace nil , I didn't know you could do that.

p-himik11:12:17

Needless to say, you shouldn't really rely on that. :)

datran05:12:36

I know this is late, but if you can send transit (edn) instead of json this is a non-issue. I also ran into this issue and switching to transit Just Worked

p-himik07:12:18

The above code has nothing to do with JSON. It's just how query parameters work. Of course you could use just a single parameter and pass it the whole transit string but it has downsides on its own.