Fork me on GitHub
#clojurescript
<
2021-05-21
>
Lu09:05:11

How should I go about converting this to cljs?

class CustomHeader {
  init(agParams) {
    this.agParams = agParams;
    this.eGui = document.createElement('div');
    this.eGui.innerHTML = `<div>foo</div>`;
  }

  getGui() {
    return this.eGui;
  }
}
What I’ve got so far is:
(defn CustomHeader
  []
  (this-as ^js this
    ;;??? init??? ...
    (set! (.-eGui this) (js/document.createElement "div"))
    (set! (-> this .-eGui .-innerHTML) "<div> foo </div>")
    ;;??? getGui ??? ..
    ))

Jakob Durstberger09:05:40

Can this just be a function that returns the div? The agParams seem to be unused anyway

(defn custom-header []
  (let [e-gui (.createElement js/document 'div)]
    (.innerHTML e-gui "<div>foo</div>")
    e-gui))

p-himik09:05:05

It might be needed for some API. If so, you should be able to just create a record.

p-himik09:05:42

And if you really need a JS class and you're using shadow-cljs, check out shadow.cljs.modern/defclass.

Lu09:05:44

@UM8P1G72Q Tried that already.. it’s returning the full html as a string in the view

Lu09:05:17

@U2FRKM4TW yeah I am using shadow-cljs.. will check out shadow.cljs.modern/defclass

p-himik09:05:38

See if you can use a regular defrecord first - way less hassle.

👍 2
emccue15:05:49

@UE35Y835W also you don't need to neccesarily create a named type if you never dispatch on it

emccue15:05:23

(ns custom-header)

(defn init [ag-params]
  (let [e-gui (doto (.createElement js/document "div")
                (set! .-innerHTML "<div> foo </div>))]

    {::ag-params ag-params
     ::e-gui e-gui}))

(defn get-gui [custom-header]
  (::e-gui custom-header))

emccue15:05:36

then you use the namespace as your "object boundary"

emccue15:05:47

and the exposed functions as your "methods"

emccue15:05:25

protocols, actual js classes, etc, are mostly useful for interop or dynamic dispatch

emccue15:05:51

you can add in dynamic dispatch to this scheme later by making public functions be protocol functions

emccue15:05:16

but if you don't need it, don't add it

emccue15:05:42

using namespaced keywords there makes it clear to other bits of code that they shouldn't be looking into those map keys - it can be a convention for stuff being "private" if you want

Lu15:05:35

Thanks! I’d need to pass the class as an argument so not sure that would work

emccue17:05:46

to some javascript code?

Lu18:05:54

Yup as a value of a JS object :)

Tomas Brejla15:05:19

Hello. I'm trying to create a small pet project in cljs (`reagent`, reframe, react-leaflet) + cljbackend (`cruxdb` , integrant , reitit). I'm also using deps.edn for dependencies, no leiningen. I originally started using shadow-cljs for building/developing the cljs frontend and everyhing was working just fine. Then I wanted to try (just being curious) how figwheel-main would work for the same project. It took me quite a while to set it up, but in the end it's somehow working. I had to provide custom externs (based on generated inferred_externs.js+ few more manual entries for leaflet.js). I'm still not sure which of the two build tools to stick with. I've found this question https://ask.clojure.org/index.php/10403/pros-and-cons-figwheel-vs-shadowcljs which seems to indicate that figwheel-mainmight be less complex and basically a "thinner wrapper" around cljs compiler itself. If using one of the tools means that I'll have to learn more useful things, I don't mind investing more time into it. So my questions are.. 1. Since the heart of my app is leaflet.js map (and I want to be using reagent+`reframe`), I guess NPM's react-leaflet is a way to go (or is there any better option?). When it comes to NPM support, can either figwheel or shadow be considered a "better choice" or both provide similar level of support? 2. Is it normal that I had to deal with inferred + manual externs when using figwheel-main, while I didn't have to deal with externs at all when I was using shadow? I might have done some stupid mistake when switching to figwheel-main, not sure. 3. Does relying on npm libs when using figwheel-main mean that it have to be using webpack internally? If so, how much details of webpack do I need to learn to efficiently use it? 4. I noticed that the "production" js-bundle generated by figwheel-main (with advanced optimizations) is way larger (1.1MB) than the production js generated by shadow (724kb). Is there any good way to easily find out what gets included in those optimized js builds? 5. are http://cljsjs.github.io/ libraries still relevant or they should no longer be needed? Any hints/help/ideas appreciated. And please no flame 🔥🤞🙂

Tomas Brejla15:05:07

Btw since I've asked quite a lot of questions, I guess it's better to discuss them here in 🧵

thheller17:05:03

IMHO this argument about figwheel being "thinner" is nonsense. You'll end up setting up the same things anyways. shadow-cljs you just get it all out of the box instead of setting up the pieces individually

thheller17:05:40

(which is more complicated as you experienced)

thheller17:05:47

but I'm obviously biased 😉

🙂 4
dnolen15:05:10

@brdloush there are variety of tools - pretty much anything could be accomplished with any of them

dnolen15:05:04

however note that everything you could possibly want to do can be accomplished w/ just ClojureScript by itself

dnolen15:05:27

like the base feature of using libs from npm etc.

dnolen15:05:14

that said - you might want a hot-reloader - and that's all you want over ClojureScript - then Figwheel suffices

dnolen15:05:52

it does provide a bunch of other things, like RN integration, many knobs specific to it's operation

dnolen15:05:23

but maybe you want a more complete build tool and you don't care about a deps.edn centric workflow

dnolen15:05:39

then shadow-cljs may be more to your taste

dnolen15:05:50

or say you want React Native and you don't care about options

dnolen15:05:04

you have only one goal - React Native - then Krell does only that

dnolen15:05:12

and has docs you can read in 2 minutes

dnolen15:05:34

and no interesting configuration of any kind to understand

Tomas Brejla15:05:22

I don't need any RN support, my app needs to be just a regular webpage (so that it can be embedded as a "webpage widget" into another native android app). I basically want to use reagent, reframe, and leaflet.js. And yes, hot-reloading is something that I definitely like to use. Not planning to use any more npm libs, so if there's some way of eliminating the need of npm and use more "cljs-only" way, I'm totally interested.

dnolen16:05:22

@brdloush you cannot really eliminate NPM - React comes from there etc.

dnolen16:05:24

and cljsjs continues to exists to support older projects - but NPM for these kinds of deps is preferred

dnolen16:05:41

going back a bit 1. matter of taste 2. seems strange 3. you have to setup manage webpack yourself w/ ClojureScript ... Figwheel hrm probably does it internally now? 4. did you gzip to see what the final difference is 5. cljsjs is still useful but not recommended

Tomas Brejla16:05:31

3) yes, fighweel-main mentions that in its documentation, that you should enable webpack via ^{:auto-bundle :webpack} metadata in their edn config. I just don't understand whether it's needed or not. Somehow I thought that all that webpack might not be needed as clojurescript compiler itself seems to have support for npm via :npm-deps. So I was hoping to avoid webpack(as I don't know it) unless really needed. For me, it's "the fewer moving parts (and magic) the better" 🙂 4) the gzipped sizes are: 196K from shadow, 289K from figwheel-main . Not much of a difference, but still it's interesting, as I'm expecting similar compilation process (and optimizations) should be triggered by both figwheel and shadow. Perhaps those manually provided externs might be the cause. The auto-generated inferred_externs.js has 110 entries and I had to manually add a few more for leaflet's L.Map and L.map (such as L.map.flyTo, L.map.on etc)

Christopher Gsell16:05:23

I am starting a new clojurescript project and in the past have used Evergreen UI as the react framework. It seems like there have been big adjustments though since I last used it as many of the elements don’t work with reagent. Is there another UI framework that people have had success using?

dnolen16:05:06

@cgsell why don't they work? If they are React components they should work just fine

Christopher Gsell19:05:06

So in version 4.0 of evergreen I can call different elements no problem. In 6.0 I call the same elements and get a blank screen with error “TypeError: inline_style_prefixer_1.prefix is not a function”

dnolen18:05:51

@brdloush fwiw I don't personally believe in avoiding Webpack and JS build tools - shadow-cljs works w/ this way and it does work for a lot of folks - but the JS ecosystem is wide and by punting the problem, more libraries and library patterns can be supported

👍 2
thheller19:05:07

you can use webpack perfectly fine with shadow-cljs if you want to. doesn't negate any of the other stuff shadow-cljs offers. shadow-cljs handling npm for you is just the default, but switching it is trivial

Tomas Brejla20:05:29

The thing is that I have no idea yet if I want or even need to use webpack or not. I've been doing mostly backend (mostly java and occasionally a little clojure) development in last decade. So I don't know much about webpack and whether I need it or not really. What I do know is that using shadow-cljs was super-easy and I didn't have any major issues. So I guess I'm switching back to shadow-cljs for now 🙂. It's not that I wouldn't like to learn more about figwheel-main, internals and options of clojurescript compiler etc. But I like that shadow-cljs just works. Which means that I can focus on learning those bits and pieces which directly relate to the app that I'm trying to build.

thheller20:05:03

that is what shadow-cljs was made for 😉

Tomas Brejla20:05:06

Thanks for the link @U05224H0W. I guess I might have some more questions regarding shadow-cljs later, so I'm joining #shadow-cljs. But I'll try to deal with those issues myself first as there's quite a lot of good documentation for shadow 👏 .

thheller20:05:44

ask away, I'll answer when I have time 🙂

dnolen18:05:34

let JS tools handle JS problems and everything will work and all JS documentation is true for ClojureScript usage as well

Endre Bakken Stovner18:05:14

Newb q: If I have a component (`#wrapper`) I want to update with a function (`update-wrapper`), what is the correct place to call that function?

(defn update-wrapper []
  (let [svgSelection (d3/select "#wrapper")
        ;; do lots of things to svgSelection ...

(defn home-page []
  (let [_ (update-wrapper)] ;; probably should not call the function here as the div#wrapper is not rendered yet
  [:section.section>div.container>div.content
   [:div#wrapper]]))

thheller19:05:59

I created an example yesterday which pretty much applies 1:1 to your case https://github.com/thheller/reagent-pdfjs

thheller19:05:24

instead of a :canvas you create a :svg element

thheller19:05:58

and you then do (d3/select (.-current svg-ref))

thheller19:05:15

the update-wrapper you call in the useEffect callback

grounded_sage18:05:28

anyone got experience with the Monaco editor library?

Endre Bakken Stovner18:05:21

I am surely doing something stupid, but... I want to translate the following call chain:

dag.idescendants().entries()
My attempt:
(-> dag (.idescendants) (.entries))
This gives the error Cannot infer target type in expression (. dag idescendants). I see that https://clojurescript.org/guides/externs#externs-inference, but the typeof the objects is only object, not anything informative like js/Foo.Bar. What do I do?

BuddhiLW19:05:00

You can use also (.. js/document f1 f2 f3 ...) equal to js/document.f1.f2.f3 So, (.. dag (idescendants) (entries)) Should work

Endre Bakken Stovner19:05:17

Thanks. That is an even nicer way to put it. But I still get the inference problem mentioned above 🙂

emccue19:05:21

@UT770EY2K Type hint with ^js

emccue19:05:04

it just needs to know to not mangle it in advanced compilation, not the exact set of methods available

🙏 2
Endre Bakken Stovner19:05:50

Thanks to you too 🙂

grounded_sage19:05:47

nvm I figured out my error when I posted here haha. Had a typo. 😅