This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-09-11
Channels
- # beginners (70)
- # clojure (34)
- # clojure-europe (1)
- # clojure-nl (2)
- # clojure-uk (3)
- # clojurescript (140)
- # cursive (6)
- # data-science (1)
- # emacs (8)
- # exercism (1)
- # fulcro (2)
- # gratitude (1)
- # helix (4)
- # hyperfiddle (5)
- # meander (3)
- # missionary (2)
- # pathom (4)
- # polylith (17)
- # reagent (7)
- # reitit (6)
- # reveal (2)
- # shadow-cljs (3)
- # uncomplicate (6)
I think you could populate the value
conditionally with a default:
:value (or @value "hello World")
Alternatively, pre-populate the re-frame db according to the form ids. Or am I misunderstanding your question?
@U018VMC8T0W okay so if I go with the first one it will be able to track my changes when I am editing the form ?
I think you can give it a try! 😄
(defn text-input [id label] (let [value (re-frame/subscribe [::subs/form id])] [:div.field [:label.label label] [:div.control [:input.input {:value @value :on-change #(re-frame/dispatch [::events/update-form id (-> % .-target .-value)]) :type "text" :placeholder "Text input"}]]]))
Hello,
What is your way of passing env variables down to CLJS and JS code? Ideally I'd like to set them up so I can acces them using process.env
I searched a lot of the internet without finding a good solution that would allow javascript and clojurescript code to access env variables
Thanks a lot for the help 😛
Options I checked out already, 1. Inline environement variables with babel in the final JS, this could work but not the best since Closure redefine process.env to global.env looks like 2. Closure-define: Looks good but I did not understand how to access the variables from pure JS code 3. Using dotenv npm module, this would be the best but I didn't manage to make it work in CLJS code
I'm targetting browser
Maybe I did not understand everything and process.env is specific to node?
someone just wrote a plugin for webpack/babel that allows you to reference them at build time
Amazing do you have the github url?
no clue, they are pretty common though. I wouldn't recommend using them for CLJS anyways
What's your recommandation for passing env vars to the runtime then?
what is your intent with those? just something that should be inlined at build time?
Yes inlined at build time is enough
Which is why babel could do the job but I was thinking about something cleaner if that exists
How can i access variables defined like this from pure JS code?
I have CLJS and JS code in my codebase, shadow-cljs will bundle all of them in 1 JS. The JS code must read the environement variable
Would be really good if my JS codebase could access variable defined using closure-define
Exactly
ok, so in your CLJS ns create a regular goog-define as described here https://shadow-cljs.github.io/docs/UsersGuide.html#closure-defines
Haha good memory yes it is
Are you suggesting to inline the env at this moment?
Not a bad idea
Oh really did not know that
well with ESM you could do import { THAT_GOOG_DEFINE } from "goog:that.cljs.namespace"
Ok I see makes sense
So my JS cannot access CLJS
Means that I have only 2 options 1. Using dotenv from npm 2. inline env variable with babel
In the end my env vars are just a map, should not be so hard to pass it to both JS and CLJS
I will check that out, thanks for the help ! 😄
Looks very hacky If I may say
i just want to pass the url of my database with env vars and others public keys used to interact with other services
It's completely runtime nop?
Haha sorry If I confused you but yes
But you have a tool that insert it in your HTML?
Ok very nice I'm interested
I will go the generated index.html approach 😛
It's true that it's cleaner like this
yeah, lets you change this stuff at actual runtime and doesn't require rebuilding your code 😛
I need to get fluent on shadow-cljs build hook ASAP so I can implement all of these routine, could you recommend me the best ressource to build one? Thanks a lot for the help !
don't start with a build hook. write a function. call the function from the REPL or command line
then if you really really want to and don't like that solution write a build hook using that actual function
Makes sense thanks
https://github.com/beetleman/shadow-cljs-hooks/blob/master/src/shadow_cljs_hooks/index.clj
build-hooks are generally overused. if your hook would run after the build completes it most likely shouldn't be a hook 😛
This hook looks perfect to build html
Haha OK I see
But in the end it makes sense that I want to customize the compilation by asking for a specific index.html nope?
If the build hook is not the solution if there something that makes more sense?
Faster than his shadow
All of this is amazing, thanks 😍 Last thing if my build command is actually npx shadow-cljs release app && shadow-cljs run ... && shadow-cljs run ...
do you have a way of specify the workflow in the config file or it would become a hook? haha
100% agree
just call (shadow/release! :my-app) (generate-my-html)
in your code (instead of the rsync from the example)
Ok I did not get it at 100% but will work at it, thanks a lot for all the good work on shadow-cljs this tool is amazing 😄
did not get it but looks very good for sure
remember. all you are writing is a clojure function. you can make that do whatever you want 🙂
but this shadow/release
would be called from the init function?
Trivial answer I think but don't get it
Ha yep ok
Haaaaaaa ok
so you create that function. and then instead of shadow-cljs release app
you run shadow-cljs run your.release/function
I run one function that would call all the shadow/release
Got it now
Thanks a lot
so you create a release build and then generate your html and whatever else you may need
perfect and I can even read from a .env file and inject it into the html
Just added to the todo I will do it tomorrow 🙂
eg. the (shadow/release :app)
in the example is identical to running shadow-cljs release app
ClojureScript and its ecosystem are just too good, it's hard to believe I just discovered it after 8 years of software engineering
although you may want to use (shadow/release! :app)
, so the code throws an exception if the compilation fails for some reason. easy to miss errors otherwise
Roger that will use shadow/release! :app
release
also prints the error, just doesn't throw. so your function will continue to run which may or may not work depending on what it does 🙂
Obviously if the compiling fails we'd like to throw an error !
for some reason this fails tho:
shadow.user> cljs.tagged-literals/JSValue
Syntax error compiling at (*cider-repl Code/helix:localhost:8777(clj)*:0:0).
No such var: cljs.tagged-literals/JSValue
:thinking_face: why would the constructor exist but the type not
shadow.user> (ns-publics 'cljs.tagged-literals)
{read-uuid #'cljs.tagged-literals/read-uuid,
valid-js-literal-key? #'cljs.tagged-literals/valid-js-literal-key?,
read-inst #'cljs.tagged-literals/read-inst,
read-queue #'cljs.tagged-literals/read-queue,
*cljs-data-readers* #'cljs.tagged-literals/*cljs-data-readers*,
->JSValue #'cljs.tagged-literals/->JSValue,
read-js #'cljs.tagged-literals/read-js}
I guess I can do this?
(cond
(= (type x) (cljs.tagged-literals/->JSValue []))
(doto (.-val x) prn)
Because JSValue
is a Java class:
Clojure 1.10.3
user=> (defrecord X [])
user.X
user=> (ns new-ns)
nil
new-ns=> user.X
user.X
new-ns=> user/X
Syntax error compiling at (REPL:0:0).
No such var: user/X
new-ns=> user/->X
#object[user$eval137$__GT_X__149 0x62e7dffa "user$eval137$__GT_X__149@62e7dffa"]
(= (type x) (cljs.tagged-literals/->JSValue []))
is wrong - you gotta wrap the second argument with type
as well.
Hello All, I am pulling my hair out over something probably super simple. I have a Material UI icon, I just need to make it green. Material UI provides this example:
<Avatar className={classes.green}>
<AssignmentIcon />
</Avatar>
So in my code I try to do this:
(mui/avatar {:variant "rounded"
:className "classes.green"}
(mui/icon-Done))
(mui/typography {} "Email Is Verified"))
The mui/avatar
is defined like this: (def avatar (interop/react-factory core/Avatar))
. When the image gets rendered, this is the browser HTML I get:
<div class="MuiAvatar-root MuiAvatar-rounded classes.green MuiAvatar-colorDefault"><svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"></path></svg></div>
Is there a different way to specify the class so that Material UI knows to make it green?can you link to the example? I suspect that isn't "classes.green"
but is an import and the .green
property is accessed
The example are here https://material-ui.com/components/avatars/
if you expand the code snippet (the first button above the snippet) you see
export default function LetterAvatars() {
const classes = useStyles();
return (
<div className={classes.root}>
<Avatar>H</Avatar>
<Avatar className={classes.orange}>N</Avatar>
<Avatar className={classes.purple}>OP</Avatar>
</div>
);
}
@U11BV7MTK, I guess this is what I am struggling with, how do you pass className={classes.orange}
to the react? I tried every possible way, :className "classes.green"
does not seem to work.
so passing :className "classes.green"
should work?
root: {
display: 'flex',
'& > *': {
margin: theme.spacing(1),
},
},
pink: {
color: theme.palette.getContrastText(pink[500]),
backgroundColor: pink[500],
},
green: {
color: '#fff',
backgroundColor: green[500],
},
and then classes.green
refers to that objectso I have to define interop for the class, correct?
OK, that makes sense, when I look at the example browser html, it shows style .jss278
like so
I guess the question is how do you call it the JS object from CLJS?
First of all, it's not "calling a JS object", it's just passing it.
If you see a.b
in JS, it will be (.-b a)
in CLJS, maybe with ^js
before the definition/usage of a
, depending on the context - more info here: https://code.thheller.com/blog/shadow-cljs/2017/11/06/improved-externs-inference.html
In this particular case, classes.green
will become (.-green classes)
, and you would need to use ^js classes
where you define classes
. Or just use (.-green ^js classes)
.
And you just pass it to the component in question:
[:> Avatar {:class-name (.-orange classes)}
"N"]
But only if life were that easy. The problem is that useStyles
that creates classes
is a hook. And for hooks to work in Reagent, you have to jump through some hooMaterial-UI v4 relies heavily on Hooks to add styling in a component. The reagent-material-ui
ClojureScript library helps a lot with the interop and how to create hooks. There’s a styles/make-styles
function there that makes life as a ClojureScript developer a lot easier. The reagent components need to use the functional style, i.e. [:f> my-component]
to be able to use Hooks.
Material-UI v5 (beta) has simplified the styling a lot, with the sx
arg. That also simplifies styling via ClojureScript a whole lot.
Here’s an example, using Material-UI v5, reagent-material-ui in ClojureScript:
https://github.com/DavidVujic/clojurescript-amplified/blob/main/src/main/app/components/greetings.cljs#L11
To add a background-color, I think this would be a way (using Material-UI v5 and reagent-material-ui):
[avatar {:sx
{:width 56
:height 56
:bgcolor "green"}}
"Hello World"]