Fork me on GitHub

how do I get calva + play-cljs to work? I'm so confused about play-cljs wanting me to use boot, where calva doesn't even mention boot


boot is just an alternative build tool to leiningen. The template that oakes provides is catered to developing with boot + nightcode, but you can modify it to use lein or clj-cli if you know how to tweak it.


If you have lein installed you can just do lein new play-cljs my-dummy-project and then convert the build.boot to a project.clj for lein. After that you can follow the other steps for getting started with calva.


alternatively you can run the equivalent commands in that tutorial as boot commands.


i.e. boot repl.


hi @U1RUG108P, thanks for your reply. sadly I don't know how to tweak it.


okay, so it's possible to run calva + boot? seems easier. I'm guessing I just need to add the dependencies (nrepl/cider/figwheel) to boot then?

👍 5

I'm very perplexed about how to get started with clojurescript, it's really hard


How do I call a multi-method from JS? I seem to be getting “is not a function” from the browser console


this works:, cljs.core.keyword("feeds")) (thanks to KLIPSE)

Yehonathan Sharvit15:02:49

Continuing on the topic of type inference, I found a simple interesting “use case” where the type inference is able to generate optimized code by not wrapping objects that are inferred as strings with an str call, as @mfikes explained it yesterday.

(defn booz [x]
  (str "Hello, " (inc x)))

(defn bar [^string x]
  (str "Hello, " x ))

(defn foo [x]
  (if (string? x)
    (str "Hello, " x )
    "No string"))
With bar and foo, x is not wrapped in a str call 🙂 You can play with it inside Klipse in order to see the transpiled code for different cases:“Hello%2C%20%22%20(inc%20x)))%0A%0A(defn%20bar%20%5B%5Estring%20x%5D%0A%20%20%20%20(str%20%22Hello%2C%20%22%20x%20))%0A%0A(defn%20foo%20%5Bx%5D%0A%20%20(if%20(string%3F%20x)%0A%20%20%20%20(str%20%22Hello%2C%20%22%20x%20)%0A%20%20%20%20%22No%20string”))


on the topic of type inference (but a little off topic for CLJS):


Hello. I have a variable which is a large String with paragraph breaks in the form of \n. I would like to split this string by the \n, and produce a new textarea with that token as the content of the textarea. When I try to set the content of the textarea, bizarre generated Javascript makes it into the content. Similarly, when I try to alert the tokens of the split, I get the alert showing some generated Javascript. See pic:


I am using reagent.


Can someone help me produce a button that will produce a new textarea DOM element for each paragraph in the String, such that that generated Javascript doesn't become part of the content, as I've been getting? Thanks!


@its.ramzi that looks like you are just passing the function as the textarea value instead of calling it and using the return value


ie. content instead of (content)


That was it! Thanks! I'm just picking cljs/reagent/clj back up after a few months off, so I'm pretty rusty. (And I was never that great!)


What am I doing wrong here? (for [s (clojure.string/split-lines content)] (js/alert s))


for returns a lazy collection. Nothing is realizing your collection so no side affects are happening


wrap it in a doall


try (doseq [s (... as that makes a bit more sense with respect to what you are trying to achieve


Interesting. I wonder why Chrome didn't give me the option to prevent further pop-ups...


So I've got what I want working with js popups. How can I do this with new textareas now? Doing simply [:textarea s] where I had (js/alert s) before isn't doing it. I am thinking I need some kind of addDomElement or addChildNode kind of function. I looked into this earlier, and got one Stack Overflow answer, but I couldn't comprehend the code or get it to work. The code clearly involved specifying some DOM element to add a child to, along with what that child's ID should be. Please tell me the simplest way to do this, what I assume to be a very common and easy, Clojurescript task. Thanks!


are you doing reagent/react or straight dom programming?


Reagent/React, I believe


I just started the project with lein new reagent-frontend mindmeld


Not that I'm opposed to vanilla js, or "straight dom programming" if it's easy enough to write in cljs.


Oh. I see what you're saying! Look up how to do the vanilla js stuff, then look up how to represent the vanilla js stuff in clojurescript. Gotcha! Thanks!


Okay, one error I got said you can't call .append on null, which makes sense to me because right now my line 11 doseq is running before the "main-content-area" DOM element is created on line 23.


But I get the same error even when I move the doseq below the home-page defn


@its.ramzi I recommend doing a Reagent tutorial first


you can’t just add vectors as dom-elements


I thought I was adding [:textarea s] as a DOM element. Is that a vector? I didn't think so...


I thought the only vector I was working with was from the string/split, but that must not be right because that's passing to a doseq, so it must be a sequence, which is a different word than vector.


can anyone clue me in — how do I await a javascript promise from a library using clojurescript?


@ccann CLJS does not support await so you do (.then the-promise (fn [val] ...))


okay cool


So... How to add a new DOM element at the click of a button? 😞


hey @its.ramzi. it looks like you have a lot of fundamental question about ClojureScript and Reagent, that might be hard to answer all of them over chat


I've tried translating the vanilla Javascript to CLJS using an online converter. No matter what I try, it is basically telling me I cannot call .append on null. So I am thinking that I do not understand the timing of when the DOM elements are created compared to when the Javascript is run.


it looks like you got linked to, which has a free 12 videos on trying to do the kinds of things you're talking about


You promise if I watch those 12 videos these answers will fall in line?


I don't promise that 😄 but you might have a better idea of how to approach these


Okay. Thanks.


to answer your latest question, there's a couple things wrong with your code you pasted above


doseq executes immediately, so it sounds like it's firing before you have rendered your "main-content-area" div to the web page


it looks like you're using Reagent, which renders asynchronously. so even if you put it after the call to reagent.core/render, it's still not guaranteed to be put on the page


Why am I wrong to think that a function to add a new DOM element to a page should be Clojurescript 101 easy-peasy?


well, it is relatively simple to add a new DOM element to a page if you just use JS interop


the problem you're encountering, is that you're using Reagent, which has opinions 😅 about how to do things. one of those opinions is that you shouldn't be mutating the DOM like you are


The first issue lilactown mentioned, about the textareas being added before the #main-content-area is on the page, would be an issue even if you were just doing JS

☝️ 5

Reagent == React + some bits. You would be struggling the same if you were just using React


Right. I jumped right to Reagent and I never went through any React tutorials. But, in my previous experience, I figured out simple helper functions, like how to manipulate the DOM in a way that I guess is against Reagent's opinions... And I was able to keep building off that. Whereas here I'm struggling to even make those initial helper functions which are required for further building.


you shouldn't need to go through any React tutorials. but it's a fundamentally different way of programming than raw JS


If Reagent's opinion is that I should not be mutating the DOM in this way... Then how do I dynamically add and remove things from a page in Reagent? I thought all dynamically adding and removing things on the page had to go through DOM. 😞


so there's some impedance mismatch


there are lots of tutorials that would help with that 🙂 e.g. the learnreagent site


There’s a concept called a reagent atom, which triggers changes to the DOM


the TL;DR is that you use reagent's state management to conditionally render certain things inside of your reagent component


In both reagent and react, you change some state, and then react tries to figure out what needs to change on the page.


So what I'm hearing is: - I should stop with vanilla JS DOM manipulation - I should study the learnreagent tutorial


Okay. Thanks for the direction.


the reagent website also has some examples to get you started:


if you want to learn reagent. it is totally fine to do straight dom manipulation but it is rather uncommon in the CLJS world


I've looked into form-1, form-2, form-3 stuff before. Am I wrong to think: Everything should just be form-3. And that all form-3's basically look a certain way. And form-3's will have the React keywords necessary for rerendering a component after a change? Can I thus skip the tutorials and just figure out how to make the glorious form-3 component with the magical keywords for rerendering?


I would say 80% of your components will be form-1. 18% will be form-2


form-3 is really for when you need to do heavy interop with either React or the DOM


Okay. I'll go through the tutorials. Thanks.


So you can compare the two, here’s your original example “reactified”:


  (:require [clojure.string :as cs]
            [reagent.core :as reagent]))

(def app-db (reagent/atom {:lines []}))

(defn content []

(defn home-page []
  (let [lines (reagent/cursor app-db [:lines])]
    (fn []
       "This is what a node looks like"
       [:div {:id "main-content-area"}
        (map (fn [line]
               [:textarea {:key line} line])

(reagent/render [home-page] (aget (.getElementsByTagName js/document "body") 0))

(swap! app-db assoc :lines (cs/split (content) "\n"))


Hello. I'm a beginner at clojurescript but have been using clojure for some time now. I'm wondering, when using clojurescript, is it normal/ideal to use clojure libraries in a clojurescript project? Or should I lean toward the javascript ecosystem when using clojurescript?

kwladyka12:02:32 here you have example how to use JS deps in CLJS.

kwladyka12:02:05 This is the hardest part. Everything else is “normal” I would say.


I tend to almost exclusively use clojurescript, there's an odd powerhouse library that I'll import


I also find in the past it's almost always been easier / more succinct to re-write my own components in clojurescript than to try to adapt an off-the-shelf javascript one

Christian Johansen20:02:15

javascript libraries also tend to have a terrible track record when it comes to backwards compat etc, so beware the cost of using them

Christian Johansen20:02:29

much less of a problem with clj deps in my experience


I see. Thanks for the info.

Christian Johansen20:02:52

1. Are you sure you need to add more dependencies? 2. Really sure? 3. Is there a clj one? 4. Would it be a lot of work to write one? 5. Is there a good JS one?

Christian Johansen20:02:02

that's roughly my decision tree 🙂


Ahh thanks this helps a lot


So I'm working on displaying a directed acyclic graph based on a vector of custom structures that basically defines a data pipeline. The data isn't in a DAG structure, but it does represent one based on the input/output pointers of each map. So my thoughts are to first put it into an actual DAG data structure (libraries exist for this) and then display it via svg and maybe canvas (libraries also exist for this).


I started to use loom, and that was when I realized I can't just pull that in and use it.


And those existing DAG libraries are Java, not Javascript, right?


If Java has the DAG library, and the image drawing library, why not just use Clojure rather than Clojurescript? Why are you keener to output the image of your graph as a SVG rather than as a PNG in your home directory? Are you running this for a personal project, or are you trying to make a user friendly page for others to use? Unless I'm way off base here... Doing a lein new reagent yourprojectname will give you a project with the Java/Javascript hookup there. So use the heavy DAG and drawing libraries server side, and just pass the final image to the browser.


Does anyone know the keyboard command to pull up nRepl in Atom in Windows? I've been looking all over for this with no luck.


@brandon.ringe for an easy way to start, there’s an existing clojurescript package wrapping the cytoscape graph library:


Apparently settings says it's Control+Alt+E. And then something flickers and disappears. 😞

Karol Wójcik20:02:27

what do you use to make http requests?


@jimberlage I actually just noticed this right before I read your message 😃. Looks awesome.


@its.ramzi Good points. This is for others on an internal team to use. I wanted something that could be easily scalable and interactive, and SVG was what I'm most familiar with in that realm. But maybe I should try to look at more java/clojure server-side processing and then sending the data to the client like you said. I'll look into cytoscape too.


I just finished lecture 4/12. These are wonderful. He's so clear. I've learned so many things that were scary looking. Like the @ So simple now. But my user experience with Atom has not been so nice. I am on Windows, and he's not. The keybinds aren't the same. I've tried installing special packages and setting up the keybinds. And I can't get the repl to play nice, or for the server to auto reload changes... Like how I know how to do in Reagent. But coding wise, he has been so clear. I'm hoping I don't have to get my IDE working like his in order to learn the code, to then go back to using lein figwheel Reagent, which I'm more familiar with.


I need to assoc a value. but I want to do it in Dev Tools’s console using javascript. Can someone tell me the correct syntax? cljs.core.assoc(re_frame.db.app_db,,,, help me please to finish this. I need to assoc a key to reframe’s db


oh… pshtt… /I’m stupid/ it’s gotta be an swap! or something


(swap! re-frame.db/app-db assoc :key :value)


yeah… now translate this to js


Oh using javascript, don’t mind me


Oh… I think this worked: cljs.core.swap_BANG_(re_frame.db.app_db, cljs.core.assoc, cljs.core.keyword("pi"), 31415926)


holy cow, javascript is darn ugly


cljs.core.swap_BANG_(re_frame.db.app_db, cljs.core.assoc, "foo", "bar");


Oh, you got it


That seems to work for me


cljs.core.get(cljs.core.deref(re_frame.db.app_db), "foo"); // "bar"


well now I actually need to use assoc-in. Does anyone know a service that compiles cljs snippets to javascript interactively? excluding all the “garbage”


klipse does that, doesn’t it?


@ag it is called “a working CLJS REPL”, it is worth it IMO 🙂


if you really want to stay in DevTools console, you could try Dirac: (I’m the maintainer)


Yeah I’ve tried Dirac once… long time ago. It was painful to setup. Maybe I should try again. The js thing I needed though for a bookmarklet


another idea: you can get working CLJS REPL via clj -m cljs.main (assuming your ~/.clojure/deps.edn contains clojurescript dep)


No, I mean Klipse thing worked for creating a simple bookmarklet. I usually don’t have to do that. It’s really indicative of something (probably awesomeness). For almost 3 years of using Clojurescript I have never, ever needed to bother about transpiled output js.


until today


so you have solved it with Klipse, nice!


just to add when I have a CLJS REPL and want to see the js code a form would generate I do something like (.toString (fn [] (+ 1 2)))


oh… yeah… that’s right


of course the tricky part is that sometimes code generated depends on your CLJS compiler environment, so it works for simpler “global” cases


It is a bit unclear - is js-arguments what you use for the Javascript arguments inside a function?

👍 5

OK, does that mean this would be legitimate use: (f.apply (js-arguments)?


(.apply f nil (js-arguments)) could work, or maybe you need to convert js-arguments to js array first


not sure if js apply can accept Array-like argument like arguments


ok, did a bit of googling, should not be needed according to:


Hmmm, I'm working from a snippet of code to fix an aspect of react (from the react devs actually). In it it has this: originalRemoveChild.apply(this, arguments)


you might need to use this-as to get the this value to pass it into .apply


yes, I have that


so something like this? (this-as my-this (.apply originalRemoveChild my-this (js-arguments)))


so, my version is : (orig-rm-child.apply this (js-arguments))


ah - I thought I could just use the same JS dotted notation. In the repl it shows x.apply (for valid x) shows as the function apply


I’m not sure, yours might work


Thanks for the help!

🍻 5

FYI - your version is correct - mine is wrong. You can use dotted notation for properties that are not functions

👍 5

So, I finished the learnreagent free course. I felt like it started to go fast super fast. I guess I'll be buying the pro course. It seemed like indenting made a difference here, and that wasn't the case in what I was used to. Maybe I'm wrong. It just seemed like everything worked out too perfectly for him. Everything rendering so neatly and nicely. With me, I couldn't add a horizontal row without it intersecting a previous DOM element.


@its.ramzi the editor setup the author is using probably includes Parinfer, which helps you align your braces and parentheses according to your whitespacing


it's not required for editing Clojure code, but some people like it


did you try following along with his examples? I believe there's a repository you can download and fiddle with