This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-09-12
Channels
- # adventofcode (1)
- # announcements (1)
- # atom-editor (4)
- # aws (4)
- # babashka (7)
- # beginners (46)
- # biff (14)
- # calva (11)
- # cljdoc (2)
- # clojure (78)
- # clojure-art (1)
- # clojure-austin (1)
- # clojure-europe (50)
- # clojure-nl (2)
- # clojure-norway (22)
- # clojure-spec (2)
- # clojure-uk (2)
- # clojurescript (72)
- # conjure (6)
- # core-typed (6)
- # eastwood (4)
- # events (1)
- # figwheel-main (11)
- # fulcro (1)
- # guix (1)
- # helix (13)
- # jobs (2)
- # jobs-discuss (4)
- # kaocha (2)
- # malli (5)
- # off-topic (7)
- # pathom (22)
- # pedestal (9)
- # re-frame (29)
- # reagent (7)
- # releases (2)
- # remote-jobs (1)
- # rewrite-clj (12)
- # shadow-cljs (44)
- # sql (13)
- # squint (2)
- # xtdb (17)
Hi, how would I use wired-button
in CLJS? https://www.npmjs.com/package/wired-elements
import { WiredButton, WiredInput } from "wired-elements"
<wired-button>Click Me</wired-button>
I've tried (:refer ["wired-elements" :refer (WiredButton)])
but I'm not clear how I get a reference to wired-button
The http://npmjs.com link above mentions "web components". Could that be the issues here?
@ben735 you don't need a reference to wired-button
, its just a web component. meaning it becomes a regular DOM element. just as you would create a div
you create a wired-button
hi, I am very new to this ecosystem, so I may have missed something obvious. I am trying to set up shadow-cljs server and use cider-connect-cljs to start experimenting. I can get REPL backed by a chrome tab, but the source file has status cider[not connected] and I cannot use M-. or C-z from it. I tried to jack-in-cljs instead (with shadow server down, to let emacs start it), and the effect is the same - I have REPL but source buffer is not "connected". I tried sesman-start first and then the usual cider-connect-cljs, but still no joy. I think the issue is similar to https://github.com/clojure-emacs/cider/issues/2939 I am also quite certain I had M-. working in sources when I was playing with figwheel-main a week ago.
For whatever it's worth, I had issues with CLJS tooling from emacs myself that was quite frustrating and I moved to VSCode and have since had no problems at all. Mine originated with figwheel and not shadow-cljs but in both cases they've been good from vscode
does anyone have a good solution to find out changes between two vectors with objects? i would preferably need deleted, changed, added
the objects is arbitrarily complex and might include arrays
By "objects" you mean plain JS objects? If so, there surely is a solution somewhere on NPM.
good point!
I randomly saw this small three.js demo on Twitter (https://twitter.com/KennethCassel/status/1569398632830435330) and decided to try out my clojurescript interop skills and see if I could quickly recreate it. I came up with this (https://gist.github.com/Chase-Lambert/9f4055ce8efcb7a1ae406cf1a8b5031d) and everything seems to be in working order (no shadow-cljs errors in the console at least) but nothing is happening in my browser. What else should I do? Any other interop advice?
Looking at the three.js github repo I'm noticing the example they give there is an even simpler rotating cube. The above example was written by gpt-3 as an interesting tidbit. I'll try the repo example and see if I get anything.
In the JS case, animate
is a plain function.
In the CLJS case, animate
is a higher order function that returns another function.
Ok, I took out the (fn []
part from my animate function
and a whole bunch of errors cascade down the console, including some infinite loop action lol.
If I take out the cube rotation stuff I get the same error but for (reading 'render')
so I am definitely doing something fundamentally wrong here. Let me try the simpler repo example.
Yeah, trying a simpler case makes sense. I just took a very superficial look at those two code samples.
This is the part that confuses me from the repo (https://github.com/mrdoob/three.js/) example:
renderer.setAnimationLoop( animation );
document.body.appendChild( renderer.domElement );
// animation
function animation( time ) {
mesh.rotation.x = time / 2000;
mesh.rotation.y = time / 1000;
renderer.render( scene, camera );
}
It has me call that animation
function with no parameters but that function seems to take a time
parameter.how do I even translate that top line to cljs? (.setAnimationLoop renderer #(animation))
? Or without the #
?
The latter, you just pass the function itself - by name or by value. But in CLJS, you gotta define that function before you pass it somewhere. Not sure whether just declaring it would do the trick - probably won't given how it's not a real name but rather a field within an NS object.
maybe time
is a field within the renderer
object? Because I have to pass that renderer
object to the animation
function anyways so I can call that render
method. I'll try that
animation
is a closure over renderer
since you create renderer
before (defn animation ...)
.
Hmmm, ok. But that animation function needs to also see scene
and camera
objects I create earlier. It's all so imperative. It's frustrating getting this translated.
Heh, yeh. But sometimes it helps to use higher order functions that you can to create closures dynamically. Not sure whether it's worth it in this case, but you can experiment with that.
Trying it as just a straight imperative translation gives me an: `three.js:19559 WARNING: Too many active WebGL contexts. Oldest context will be lost. three.js:19850 THREE.WebGLRenderer: Context Lost.` warning.
Not being able to translate 16 simple lines of JS to CLJS does not bode well for my hoped for future as a full stack Clojure developer. lol! Interop was supposed to be seemless. haha
That warning sounds like an artifact of hot code reloading. Does it work? Are the warnings still there if you just refresh the page?
I had a cube for a second and then made some changes and it's gone. Then my undo didn't work correctly and I can't get back to the old state. Can't figure out why. Here is the full code of the example:
import * as THREE from 'three';
// init
const camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animation );
document.body.appendChild( renderer.domElement );
// animation
function animation( time ) {
mesh.rotation.x = time / 2000;
mesh.rotation.y = time / 1000;
renderer.render( scene, camera );
}
Sorry to be taking up so much time, but how would you change my code to match that better: https://gist.github.com/Chase-Lambert/9f4055ce8efcb7a1ae406cf1a8b5031d> and then made some changes and it's gone This means that the code is not hot-code-reloading-friendly. No idea how to make it friendly though - depends on the three.js library and might even be impossible.
Not sure what you mean by "what to return". It's perfectly fine not to return anything.
(.setAnimationLoop renderer (animation renderer mesh scene camera))
Here, you're calling the animation
function and pass its result to .setAnimationLoop
.
In JS, the animation
function itself is passed to that method - because that method calls it.
Ahh ok. So I'll just pass in (.setAnimationLoop renderer animation)
like you told me before. And then maybe at the end of cube
(thanks for clarifying I don't need to return anything) I was thinking of doing the whole (animation renderer mesh scene camera)
because I don't know how or when else to feed all those objects to the animation function.
With that though I'm getting another uncaught typeerror, this time on "rotation" in my animation
function.
In the JS code, the animation
function accepts just one argument. In your variant, it accepts many.
That's what I meant by dynamically creating closures:
(defn make-animation-fn [renderer mesh scene camera]
(fn animation [time]
...))
(.setAnimationLoop renderer (make-animation-fn renderer mesh scene camera))
interesting solution. I did not grasp what you had meant when you originally said "dynamically creating closures"
I'm still not understanding how animation
knows what time
is. I don't know what time
is. lol
Ok. Yeah, I'll admit I hadn't actually dug into the three.js docs yet. I didn't anticipate the short example kicking my butt so hard. Thanks again for your patience and help.
No problem. :)
I don't know tree.js either. I'm just judging by that function animation( time ) { ... }
Just looking at this one bit of your question:
renderer.setAnimationLoop( animation );
...
function animation( time ) { ... }
> It has me call that animation
function with no parameters but that function seems to take a time
parameter.
This code does not "call" animation
. It only passes a reference to that function into renderer.setAnimationLoop
. Presumably this will be called repeatedly from within the loop, passing in time
each time it does.
Hope that might help some.Yes, thanks for that clarification. It took a while for my brain to wrap itself around what was happening there. I got frustrated but in hindsight the interop really was quite straightforward.
And without looking into three.js code myself, I would predict that it uses requestAnimationFrame
under the hood, which on each "frame" provides a DOMHighResTimeStamp
, which it will then pass along to your animation function as time
.
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
I'll check this out, I love the MDN docs. Another thing I need to go review again is how to inspect these objects in the developer console. I was getting minimal error support or anything telling me where I was going wrong.
CLJS classpath Q: shadow-cljs is failing to build my app bc it says my core.clj
file was found on the classpath but the namespace of that file cannot be found? I think I might've goofed with a require or something and don't know how to undo it. builds were working fine previously
The required namespace "traintime.core" is not available.
; "traintime/core.clj" was found on the classpath. Should this be a .cljs file?
I just found that namespace in manifest.edn
is it ok to take it out? bc it's not in classpath.edn
where I expected it might be from that message
It shouldn't be. traintime.core
is the namespace of one of my .clj
files but its for backend stuff. but I don't think I can use Clojure namespaces in CLJS files right? and I did require said namespace bc I forgot about said (possible) restriction
> but I don't think I can use Clojure namespaces in CLJS files right? Right. You can, but only for macros. And that has to be handled in a somewhat special way.
Would that at least go some way toward explaining this error? And if so, how could I undo it?
Ehm, it could. And no clue without knowing what you're doing exactly.
Seems like you're requiring traintime.core
from a CLJS namespace, but traintime.core
is a CLJ namespace. So just stop requiring it if you don't need it. Or make it into a .cljc
file if you need that functionality to be available in both CLJ and CLJS contexts. Or require it as a macro namespace if you need just a macro from it - but better yet, read how to create .cljs
and .clj
files together for macros so that requiring macros becomes easier.
my shadow-cljs.edn
had the incorrect namespace for the :init-fn
key