If you receive Hiccup, you can just modify it as a regular data structure before embedding it into a higher order component.
Has anybody encountered issues passing MetaFn
to JS functions? MetaFn
isn’t a native JS function, so it isn’t executed as expected. For example:
(js/window.setTimeout #(js/console.log "execute native function")) ;; works
(js/window.setTimeout ^:private #(js/console.log "execute function with metadata")) ;; doesn't execute
I would have expected this to be documented somewhere, or be accounted for in JS interop.Hi, I'm getting this error: Caused by: http://java.io.FileNotFoundException: Could not locate cljs/repl/nashorn__init.class or cljs/repl/nashorn.clj on classpath. I'm doing java -cp cljs.jar;src clojure.main repl.clj. It's from the book ClojureScript unraveled. I assume Nashorn is deprecated, but what is the alternative? Thanks.
An alternative would be running a NodeJS REPL.
I'm using clj
and I have this alias in my ~/.clojure/deps.edn
:
:cljs-repl {:extra-deps {org.clojure/clojurescript {:mvn/version "RELEASE"}}
:main-opts ["-m" "cljs.repl.node"]}
which can be used as clj -Mcljs-repl
.It's the same for any CLJS type that implements IFn
. Keywords, sets, maps, vectors, vars, maybe other things.
Interop is finicky in some places, this is one of them.
I'm running this command on WSL2 (Ubuntu) on Windows 10 and Google Chrome starts up (on Ubuntu, displayed on Windows 10 via VcXsrv) but I never get the REPL prompt -- suggestions for troubleshooting this?
$ clojure -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "RELEASE"}}}' -M -m cljs.main
The browser shows this URL <http://localhost:9000/?rel=1612464229362>
and the expected cljs welcome page, so that part is working...
Chrome Version 88.0.4324.96 (Official Build) (64-bit)
Does the network tab show a pending request to localhost (just in case - you should refresh the page after opening dev tools for that tab to have something)?
Thank you. i'll try the node js repl next. i don't use lein or clj yet. i'm trying to understand how clojurscript works on a low level.
clj
is just a way to create a classpath for a Java command, it has nothing to do with CLJS.
I don't know what cljs.jar
contains but you can try running java -cp cljs.jar;src clojure.main -m cljs.repl.node
.
Will try that... just a sec...
Yup, looks like the last request just hangs:
{:repl "Thread-620", :type :result, :content "{:status :success, :value \"\"}", :order 2}:
Yeah, it's supposed to be that way - long polling. Hmm, not sure then.
Thanks. This all just works on macOS and I think it's the first time I've tried on WSL2/Windows 10.
Just out of interest - does it work without WSL2?
Heh, how am I going to start a REPL without WSL2? I don't have clj installed on Powershell etc.
FWIW, hitting the WSL2 process from Windows via 172.17.159.136 doesn't work either in exactly the same way.
clj
just creates a classpath - you have said it yourself. :) You can run the Java command manually.
Haha... touche! I don't even have java
installed on Powershell.
You mean, there's no Java installed anywhere in the system but inside WSL2? Because I'm not sure what Powershell has to do with it - Java is just a regular executable that can be run by any means.
In any case, I was just curious, nothing more.
Unless someone else can chime in with some ideas, I would try to debug cljs.repl/repl*
, namely its need-prompt
part.
(interestingly, for some reason it uses (identity true)
instead of just true
, huh)
Right, I don't do any dev outside of WSL2 so there are no dev tools installed on the Windows side.
You asked "does it work without WSL2" and there's no way to run Java or Clojure on my machine outside of WSL2.
I see. It's just that I used to have Java installed back when I was using Windows not because I did my development there but because something else needed Java. :) "Billions of devices!"
So far nothing has needed Java on Windows 🙂
Oh, does the regular clj REPL prompt appear?
Yeah, I do loads of Clojure work on this setup. And I've also had Figwheel Main run fine on this setup.
So it's just the plain cljs REPL.
Yup, just tested Figwheel...
clj -Sdeps "{:deps {com.bhauman/figwheel-main {:mvn/version \"0.2.12\"}}}" -m figwheel.main
Starts the browser, produces a REPL, all works.Hmm, I'm getting
Failed to launch a browser:
The BROWSE action is not supported on the current platform!
Ah, apparently VirtualBox cannot work with WSL2 at all.
Why does *ns*
in clojurescript return nil
?
because it doesn't exist in the REPL technically, should only be used in macros
Yup I can confirm it. Thanks
On Web Workers. Anyone managed to pass CLJS maps between different contexts without serialization? I’ve posted this on reddit for indexation purposes. https://www.reddit.com/r/Clojure/comments/ld5f2h/cljs_web_workers_transferable_db/
I'm new to clojure/clojurescript and thinking about the possibility to make a macro somehow that builds defines static variables of paths in a map?
The reason is that i would like to pass paths in state to different functions when rendering my hiccup
that way i could more easily reuse components of my UI in different parts of my state
I would like to have them statically defined so that when something changes i get notified by the compiler
the solution i use now is to
(def state-path-login-username [:login :username])
but if i have to keep these defines in sync with the model
is it even possible to write a macro that does this?
Do you meant that you want to be able to have something like this in your code
(generate-state-path-defs
[:login :username]
[:login :password]
[:some :other :state])
and end up with
(def state-path-login-username [:login :username])
(def state-path-login-password [:login :password])
(def state-path-some-other-state [:some :other :state])
being actually compiled?well thats a start
but maybe more like this
(defstate {:login {:username "" :password ""} :other-state...})
and end up with something like this
(def state (r/atom {:login {:username "" :password ""} :other-state...}))
(def state-path-login-username [:login :username])
and so on
It is possible. The first step would be to turn the map into a collection of vectors with all possible paths.
The second step would be to write macro that generates those def
statements and, it seems, a ratom, based on that collection of vectors.
The first step is actually a bit harder to implement than the second one and it has nothing to do with macros.
If you want to learn more about writing macros to be able to implement the second step yourself, I find this article quite good to get started with them: https://www.braveclojure.com/writing-macros/
One thing to note - [:a-b]
and [:a :b]
will generate the same exact symbol for def
in your case. Something to be aware of. Either of the steps could make the check and report any collisions.
Another thing - your IDE probably won't be able to figure out that there are some generated def
statements. So no autocompletion and symbol resolution unless you customize it yourself.
ok, thanks ill look into it. But then i know it wouldnt be futile to give it a try
👋 , any recs on the best way in 2021 to start on a cljs project where I can’t use JVM at all (target processor has no JDK)?
you don't need the JVM on the target once everything is compiled
I’m tempted to start from #klipse, and remove pieces I don’t need, rather than work the other way….. my ideal would be a shadow-cljs
level of featured REPL, but running on and accessed in the browser rather than from terminal
I need CLJS scripting as a user feature in the webapp
And ideally, it would be homogenous toolchain with how I write the core
https://code.thheller.com/blog/shadow-cljs/2017/10/14/bootstrap-support.html
Cool, I read through that, I wasn’t sure how relevant it still was in 2021
hasn't changed
I’ll try to make a clone-able github repo that provides an example of this pattern
oh…. @thheller hahaha, just recognized the name 🙇
@thheller I got a sense from your blog that this is sort a “yeah, you can do this, but its not a great path yet, avoid if you don’t really really need it”
Does that seem accurate?
if you need to eval
at runtime thats the only path to do it apart from a slightly less powerful eval using https://github.com/borkdude/sci
and yes, if you don't really need eval
then you shouldn't do it as it makes the build rather large
kinda depends on what kind of eval
you are talking about
Having trouble using base64 encoding a file from a file uploader and getting into the body of a request.
(defn form
[]
[:div
[:form {:id "upload-form"
:enc-type "multipart/form-data"}
[:label {:for "upload-file"}
"upload"]
[:input {:type "file"
:id "upload-file"
:name "upload-file"
:accept "image/jpeg"}]
[:button {:on-click #(upload-file "upload-file")}
"button"]]])
(defn put-file-in-bucket [file path]
(PUT (str endpoint "/photo/bucket-name/" path)
{:handler handler
:error-handler error-handler
:body file}))
(defn upload-file [element-id]
(let [el (.getElementById js/document element-id)
file (aget (.-files el) 0)
file-name (.-name file)
reader (new js/FileReader)
binary (.readAsText reader file)
b64 (js/btoa binary)]
(put-file-in-bucket b64 file-name)))
That is as far as ive gotten so far but when i console.log the results of (.readAsText reader file) it comes back as undefined and same as when i use (.readAsBinaryString reader file).@thheller Hi, build size is no worries for this use, since its cached on-device
@snickell you can try sci cljs eval here: https://nextjournal.github.io/clojure-mode/
there is a #sci channel if you want to know more
Those functions don't return anything. They change the reader in-place.
All file operations are async, you cannot directly get a result from something like that - you have to chain the actions together with promises or events.
ah ok that makes sense
i found this code online
input.onchange = function () {
var file = input.files[0],
reader = new FileReader();
reader.onloadend = function () {
// Since it contains the Data URI, we should remove the prefix and keep only Base64 string
var b64 = reader.result.replace(/^data:.+;base64,/, '');
console.log(b64);
};
the only thing i dont understand is how to use interop on the reader.onLoadEnd = function() …
would it be (def on-load-end (.onLoadEnd reader #(,,,)
?
Hey! We have a JavaServerFaces app with some JavaScript code (inlined as well as in js-src). So we're working with post-backs and page-loads/navigation all the time. What could be a migration path to first using CLJS for better UX and later switch to SPA and get rid of JSF? A naive idea would be to just replace the JS with CLJS, but we would be loading it over and over again. May be not too bad since it's an internal app so little latency and much bandwidth and browser cache. Would wrapping the JSF app in an IFRAME help? So load the CLJS just once and keep it while doing the JSF navigation just in the IFRAME. I'm not an expert browser/JS developer so I wonder if that could work. Any thoughts? Anyone else mixing JSF and CLJS?
(set! (.-onloadend reader) (fn [event] ...))
This is a decent cheat sheet: https://cljs.info/cheatsheet/
@borkdude so cool!
if you ask me: self-hosted yields a bigger bundle size (about 8mb unzipped, 1mb zipped) but bundles a full compiler: the code it generates is more performant than an interpreter. sci offers a (significant) subset of clojure as an interpreter: smaller bundle size, but the code in it will not run as performant.
Got it! I’m running on an embedded device without JVM support
So bundle size is not a concern
sci can run in advanced compiled CLJS and can hook into your advanced compiled functions, which may compensate performance issues
I think….. repl tooling and features, and performance of compiled code are probably my emphasis?
whereas self-hosted cannot run in advanced mode
oh interesting!
@snickellto go back to your original problem: > to start on a cljs project where I can’t use JVM at all (target processor has no JDK) why don't you compile on another machine which does have a JVM and then move the JS to the device that doesn't have a JVM?
I mean, browsers don't have a JVM either (well, let's ignore applets). That's no reason to not use CLJS + JVM for dev
I need to compile potentially complex user entered scripts
(or interpret)
right, gotcha. yeah, then self-hosted or sci makes sense.
thanks, I appreciate your feedback, you always know least when you start on a new area
You’re helping me not blow my foot off while I figure out the self-hosted area
Thank you. I’ll try that out later today
Hello all, why is so complicated to add npm dependencies to a clojurescript project? Do people use shadow-cljs for it? I am just trying to add react and testing libraries (https://testing-library.com/) along with react. and figwheel and clojurescript. Can someone let me know what is the stack to create a project TDD based with clojurescript?
@ricardozcabral I suspect a lot of folks doing ClojureScript just use clojure.test
because it's built in and then use one of the various cljs test runners (I use the CLI/`deps.edn` rather than lein
so I use Olical's cljs-test-runner for some stuff and I just started using Figwheel Main and I seem to recall that automatically runs your tests for you and can display them in a browser).
(and, so far, I've managed to avoid npm
and any dependencies from that!)
https://github.com/Olical/cljs-test-runner I like this one