This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-10-14
Channels
- # announcements (9)
- # beginners (49)
- # calva (26)
- # cider (6)
- # clj-kondo (17)
- # cljsjs (1)
- # cljsrn (2)
- # clojure (72)
- # clojure-europe (5)
- # clojure-france (8)
- # clojure-greece (1)
- # clojure-italy (5)
- # clojure-nl (9)
- # clojure-spec (49)
- # clojure-uk (17)
- # clojuredesign-podcast (13)
- # clojurescript (137)
- # cursive (15)
- # data-science (1)
- # datomic (55)
- # duct (2)
- # emacs (5)
- # figwheel-main (11)
- # fulcro (11)
- # graphql (1)
- # hoplon (1)
- # instaparse (1)
- # jobs (12)
- # jobs-rus (1)
- # leiningen (1)
- # nrepl (34)
- # nyc (2)
- # off-topic (1)
- # onyx (1)
- # pedestal (1)
- # re-frame (6)
- # reitit (3)
- # remote-jobs (1)
- # shadow-cljs (196)
- # sim-testing (1)
- # spacemacs (9)
- # sql (1)
- # vim (70)
- # xtdb (31)
i have an expression
(->> [:#container
[[:p {:margin-bottom "8px"}]]]
garden.core/css)
is it possible to define a var that contains a result of this expression at compile time?Hello guys, I need a little help with shadow-cljs. I can't make the css hot reload work.
this is my filesystem
and this is my lein-shadow config
don't set :watch-dir
or :watch-path
at all and it should just work. assuming you are including the css via <link rel="stylesheet" href="/css/site.css">
unfortunately it doesn't work this way either. I have a http-kit server, and this is where I link my css. (live reload of code works, only css doesn't)
so you are not using the built-in server on port 3000? you can then remove the :http-port 3000
from the config and just add :watch-dir "resource/public"
(no :watch-path
)
this is my nem config. still doesn't work though 😞 (anyway, I am fascinated by your work on shadow-cljs)
did you check the devtools requests panel? or console? it might be sending the request and your webserver just might provide the old version?
and check if there is an actual <link rel="stylesheet" href="/css/site.css">
in your HTML. not sure what include-css
actually emits?
well I checked the devtools, it wasn't there, the link was okay. I spent some hours with it then it magically started to work again. I looked at https://github.com/jacekschae/shadow-reagent , downloaded it, tried it out to see it work, and when I started my original project css reload worked 😄 Thank you for cleaning up my misunderstanding about http-root and helping me repair my config!
the :source-paths
you can probably also remove unless lein-shadow
does something with them. shadow-cljs
won't use them if you use lein
.
I call shadow-cljs from the repl with (dev). Thank you, I removed :source-paths aswell.
(defmacro compile-time-value []
#?(:cljs (->
[:#popup-container
[[:p {:margin-bottom "8px"}]]]
garden.core/css)
:clj ""))
here is the link https://cljs.github.io/api/cljs.core/defmacro
it should work without the reader conditional, because macros are run in clojure (assuming you're not self-hosted).
try adding a (:require-macros [your-ns :refer [compile-time-value]])
to the cljs namespace
this might help. https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html
please stop using :require-macros
in consumer namespace. the only :require-macros
you should ever have is (ns some.thing (:require-macros [some.thing]))
so its own name
I have a let statement with a reagent atom, and within the let I have a for. I want to reset! the value of my atom from within the for loop but it seems like it don't have access to my let variable from there?
(defn box [element]
(let [selected-box (reagent/atom "")]
(for [option (:options element)]
^{:key option} [:div.box
{:on-click #(reset! selected-box (:value option))}])))
@olle142 your atom is being redefined at each rerender. You need to use reagent form 2 .. which means wrapping your dom elements (your for loop) with an anonymous function
If I want to add a class to my :div.box based on selected-boxs' value, do I have to force a rerender or something?
@olle142 Not really 🙂 You can simply do:
[:div.box
{:class (if (= @selected-box "your-value")
"this class"
"other class")
:on-click #(reset! selected-box (:value option))}]
Whenever your selected-box
atom is reset you're guaranteed that the re-render happens and the if statement will be evaluated again to assign the right class 🙂
Does someone has face it before?
Hi @ramon.rios, can you share your code here ?
Just a sec
That's my view
(defn role1-panel []
[:div ])
(defn role2-panel []
[:div [:h1 "Hello from role2!!!"]
[:a {:href (routes/home)} "Home"]])
(defn role3-panel []
[:div [:h1 "Hello from role3!!!"]
[:a {:href (routes/home)} "Home"]])
(defn role4-panel []
[:div [:h1 "Hello from role4!!!"]
[:a {:href (routes/home)} "Home"]])
(defn home-panel []
(fn []
[:div
[:h1 "Main Menu"]
[:ul
[:li [:a {:href (routes/role1)} "Role 1"]]
[:li [:a {:href (routes/role2)} "Role 2"]]
[:li [:a {:href (routes/role3)} "Role 3"]]
[:li [:a {:href (routes/role4)} "Role 4"]]
[:li [:a {:href (routes/home)} "Home"]]]]))
(defn main-panel []
(let [p (rf/subscribe [:db-admin-service/current-panel])]
(js/console.log "current panels" p)
(if-let [c @p]
[c]
[home-panel])))
That's my subs.cljs
(def components-per-id {:home-panel [v/home-panelsu]
:role1-panel [v/role1-panel]
:role2-panel [v/role2-panel]
:role3-panel [v/role3-panel]
:role4-panel [v/role4-panel]})
(rf/reg-sub
:db-admin-service/current-panel
(fn [db]
(js/console.log "isso funciona mesmo?")
(get components-per-id (d/current-panel db))))
my routes
(defn select-menu
"Dispatches an event that selects the given menu. Any parameters can also be passed on."
[id & [params]]
(rf/dispatch [:db-admin-service/select-menu id]))
(defroute home "/" [query-params]
(select-menu :home-panel query-params))
(defroute role1 "/role1" [query-params]
(select-menu :role1-panel query-params))
(defroute role2 "/role2" [query-params]
(select-menu :role2-panel query-params))
(defroute role3 "/role3" [query-params]
(select-menu :role3-panel query-params))
(defroute role4 "/role4" [query-params]
My issue was that i was returning a vector inside other vector
As soon as i put a 3 vector it worked
Hi @ramon.rios, can you share your code here ?
quickstart question on Windows: Exception in thread "main" java.nio.file.InvalidPathException: Illegal char <:> at index 2: /D:/xx/xx/xx/src/clojure/test/out/cljs/core.js
from this command: java -cp "cljs.jar;src" cljs.main --optimizations advanced -c test.core
I'm trying to call var provider = new firebase.auth.GoogleAuthProvider();
.
Did this: (ocall firebase "auth.GoogleAuthProvider")
Got this:
app.js:2176 failed to load shadow.module.app.append.js TypeError: this.wa is not a function
at (auth.js:134)
What am I doing wrong?assuming that firebase
was your :as
alias in the :require
you probably just want firebase/auth.GoogleAuthProvider
?
Yea that actually worked, but how can I execute something like this: firebase.auth().signInWithPopup(provider).then(...).catch(...)
you can call a method on an object like (.foo bar)
where foo
is the method name and bar
is the object
Well I couldn't make it work... Executing this: (println (-> (firebase/auth) (.signInWithPopup (firebase/auth.GoogleAuthProvider))))
resulted:
app.js:2176 failed to load shadow.module.app.append.js TypeError: this.wa is not a function
at (auth.js:134)
at Function.d [as GoogleAuthProvider] (auth.js:359)
at Object.ui$auth$core$auth_init [as auth_init] (core.cljs:17)
at Object.ui$core$mount_root [as mount_root] (core.cljs:18)
at Object.ui$core$init [as init] (core.cljs:25)
at eval (/js/compiled/cljs-runtime/shadow.module.app.append.js:2)
at eval (<anonymous>)
at Object.goog.globalEval (app.js:827)
at Object.env.evalLoad (app.js:2174)
at app.js:2431
And actually, just running this (firebase/auth.GoogleAuthProvider)
result in the same error
seems like you are maybe calling it before initializing something else you are supposed to initialize?
(ns ui.auth.core (:require ["firebase/app" :as firebase] ["firebase/auth"] [oops.core :refer [oget ocall]]))
but its a constructor so you should call it as (firebase/auth.GoogleAuthProvider.)
maybe?
I read the warning of oops
and the advanced renaming. is it safe to use interop this way?
cljs-oops
is working around really really old problems that are either fixed or have "easier" solutions
90% of the problems it solves are better solved via https://shadow-cljs.github.io/docs/UsersGuide.html#infer-externs
:as firebase
sets up a namespace alias. so it should be used as such (ie. firebase/*
)
the dot form also works but the compiler handles it slightly differently. mostly works but more stuff you have to watch out for (eg. var shadowing)
@lilactown you should give it a try and let us know. 😉 if you also run into the hawk issue I'll need to figure out how to detect catalina and disable it by default
lol. I just sent an @all at work telling people not to upgrade until I can verify. I am going to try and get ahold of someone who’s already done the upgrade
I’ve been using Catalina with various ClojureScript projects for the past few months—I saw no issues.
Is there any existing library or tool which reads a typescript .d.ts
file and generates clojurescript bindings for that typescript file? Wanted to check before I see about hacking one up
what kind of bindings do you have in mind? you don't really need bindings if you can just call the code directly anyways?
Well I'm still hung up on the autocomplete thing. I can get autocomplete on my own namespaces, so I figured it wouldn't be to hard to have a script that generated all the stuff I would write by hand anyway so I could get some autocomplete in Cursive
Cause yeah shadow-cljs
makes it super easy to ensure the javascript is included and accessible, but it would be real nice if I didn't have to jump into an npm libraries docs to figure out the API
I thought I had found something with https://github.com/angular/tsickle but I missed the s
in Closure
there 🙂
but cursive has this feature to generate "stubs". not sure if you can actually abuse this but it basically does the same things to provide a bit more completion for macro generated code
Kotlin's dukat
tool is trying to do something like this, but it's way harder for Kotlin, cause it's trying to reconcile two very different type systems. For clojurescript I think I just need to look for export class
and export function
and get the names of the parameters and dump those to a cljs file
maybe cursive supports the closure output though. not sure how much of the closure library it actually supports
I mean I haven't done anything yet so there's probably something I'm not thinking about, but figured I'd ask first
Sure, I'm just going for 80% useful. My day job is typescript + kotlin, and we rarely use an npm library that doesn't have a decent set of typescript bindings, and those are fairly predictable.
No idea if it'll work, but would be neat if I could just run something against a .d.ts
and generate some basic cljs to work with
Would it create stubs? Bit like the datomic stubs cursive creates..? That’s a fun idea.
Lack of completion for interop does make exploring js libraries a little slow and error prone.
As @U05224H0W mentioned below, I guess it’s part of the externs puzzle. Cursive adds stubs to the classpath, I think, to enable completion during dev. Making those stubs and doing something similar would be super cool.
Yeah absolutely. Just stubs. I'm looking around there isn't a super simple thing to use to look at a .d.ts
file and get the exports. For a proof of concept I'll probably just try some regex.
Yeah I'm not sure how it would really work in the larger picture, proof-of-concept I'll just dump the stubs to src/ts/...
for now.
I'm trying to see if there is some way to get tsc
to dump an AST, but ain't seeing anything yet
Hmm, and Kotlin is trying to solve this problem too: https://github.com/Kotlin/dukat However, clojurescript doesn't care about the types, which should make this way simpler. I wonder if I can hack the final output step to generate the clojurescript bindings 🙂
I think it might not be too crazy cause cljs really would only care about the class/function name and it's args. The cljs doesn't care if the args have super crazy extended types so we can ignore them. Kotlin on the other hand has to do some legit gymnastics to reconcile literal types
into kotlin code that's still adhering to a JS api