This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-06-07
Channels
- # announcements (2)
- # asami (2)
- # babashka (15)
- # babashka-sci-dev (31)
- # beginners (130)
- # boot (4)
- # cider (5)
- # circleci (12)
- # clj-kondo (10)
- # cljs-dev (8)
- # clojure (7)
- # clojure-czech (14)
- # clojure-europe (19)
- # clojure-france (5)
- # clojure-uk (2)
- # clojured (23)
- # clojurescript (11)
- # conjure (8)
- # datomic (5)
- # emacs (1)
- # etaoin (8)
- # events (2)
- # fulcro (10)
- # graalvm (18)
- # gratitude (1)
- # holy-lambda (16)
- # honeysql (4)
- # introduce-yourself (1)
- # jobs (2)
- # kaocha (3)
- # london-clojurians (1)
- # lsp (53)
- # off-topic (16)
- # other-languages (2)
- # pathom (4)
- # pedestal (3)
- # podcasts-discuss (1)
- # portal (10)
- # re-frame (69)
- # reitit (2)
- # shadow-cljs (11)
- # vim (7)
- # xtdb (29)
Hello, I'm wondering why the following does (not) work:
I want to get the name (in string format) of the file I just uploaded using <input type="file">
This doesn't work:
[:input
{:type "file"
:id "my-img"
:name "my-img"
:accept "image/*"
:on-change (fn [e] (.log js/console (get (-> e .-target .-files) 0)))}]
;; log `null' in the console
I also tried to detect if I got a FileList
(as explained by https://developer.mozilla.org/en-US/docs/Web/API/FileList):
:on-change (fn [e] (.log js/console (-> e .-target .-files)))
;; this does log the file list into console
But array?
and object?
all return false
:on-change (fn [e] (.log js/console (array? (-> e .-target .-files))))
;; log `false' in the console
I searched online for a while and found https://tech.toryanderson.com/2021/11/06/uploading-files-and-handling-upload-requests-in-clojurescript/#ajax-submissions uses aget
instead:
(defn submit-image
"submit the selected image that is on input `#input-id`"
[input-id]
(let [el (.getElementById js/document input-id)
name (.-name el)
file (aget (.-files el) 0) ;; this line indicates using `aget'
form-data (js/FormData.)
_ (.append form-data "file" file)
submit-params {:uri "/upload-image"
:body form-data
:method :post}]
(rfc/dispatch [:upload-image submit-params])))
So I tried it out and this time the code works
:on-change (fn [e] (.log js/console (.-name (aget (-> e .-target .-files) 0))))
But I don't see why.@U2FRKM4TW Hi, thank you. That's actually the question I want to ask. I'm sorry I messed again with the Slack's line-break (Shift+Enter). I've edited my question:
Why aget
works? The https://clojuredocs.org/clojure.core/aget explains:
;; aget can be used to check the existence of an element
;; this approach works with documents in ClojureScript where core/contains? does not
(aget js/document "getElementById")
;;=> #object[getElementById "function getElementById() { [native code] }"]
(contains? js/document "getElementById")
;;=> false
But there is not even an entry in https://cljs.info/cheatsheet/.
Did you happen to know if there is other info on this topic? Thank youDon't follow that comment - it's misleading. While it does work right now, it's not a part of its contract. Instead, if you need to get an attribute of some object, use either interop (just like you did with e.g. .-target
) or goog.object/get
(useful for when the name of the attribute is in some variable).
aget
is for arrays, that's it. In Clojure, it's Java arrays. And in ClojureScript, it's JavaScript arrays.
get
didn't work in your case because get
is for associative CLJ/CLJS data types. A JS object is not such a type.
Regarding why aget
works on something for which array?
returns false
- that's because array?
checks only for a specific type of array, the js/Array
.
But JS has plenty of other arrays and array-like structures. FileList
being one of them, Float64Array
being another.
BTW, not that it's important, but you can avoid aget
in this specific case altogether because FileList
has a method called item
. So you can use (.. e -target -files (item 0))
.
Thank you so much for the detailed information. 👍 I did try using the item
method, but perhaps I messed up with other places so I finally landed on aget
in my case. I'll try item
again. Now all of this is much clearer to me. 🤓
@dnolen Is your 2013 answer still relevant in 2022, please? https://stackoverflow.com/a/16670400/5773724
Perfect, thanks @dnolen!