Fork me on GitHub
#clojurescript
<
2019-05-14
>
wilkerlucio03:05:34

hello, I'm trying to integrate code with some JS api that extensively uses JS classes, I've tried to write some helpers to make class definitions on the cljs side, but I'm having trouble to call the original class constructor, by their API definition I must extend their class and call super on it, but when I try to call the constructor directly it throws Cannot call a class as a function

wilkerlucio03:05:50

this is how I'm trying to do it:

wilkerlucio03:05:51

(defn js-class [{::keys [constructor] :as definition}]
  (let [c     (or constructor (fn []))
        proto (gobj/get c "prototype")]
    (doseq [[k v] (dissoc definition ::constructor)]
      (case k
        ::extends
        (do
          (gobj/extend proto (gobj/get v "prototype"))
          (js/Object.setPrototypeOf c (gobj/get v "prototype")))

        (gobj/set proto (name k) v)))
    c))

(def NumControl
  (js-class
    {::extends     js/Rete.Control
     ::constructor (fn [emitter key readonly]
                     (let [this (js-this)]
                       (.call js/Rete.Control this key)
                       (gobj/set this "render" "react")
                       (gobj/set this "component" ReactNumControl)
                       (gobj/set this "props" {:emitter emitter :ikey key :readonly readonly})))}))

wilkerlucio03:05:19

the problem is the line that does (.call js/Rete.Control this key), that throws the error... is there a way around this?

lilactown03:05:22

And I think I copied most of it from a gist somewhere

wilkerlucio03:05:24

@lilactown thanks, that's much cleaner, but I don't see it calling the parent constructor, you have some example of that?

wilkerlucio03:05:22

I did checked the source of goog/inherit, but seems like it depends on its own implementation to call the parent constructor (it sets constructor as a property in the prototype)

lilactown03:05:31

My googling tells me you might need to use the ‘constructor’ property

wilkerlucio03:05:38

but when I try to call that same thing from a class defined by js, that's illegal

wilkerlucio03:05:50

throws Cannot call a class as a function

lilactown03:05:06

> However, the example above notably avoids doing anything in the constructors. In particular, it avoids super, a new piece of syntax that allows subclasses to access the properties and constructor of the superclass. This is much more complicated, and is in fact impossible to fully emulate in ES5, although it can be emulated in ES6 without using class syntax or super through use of Reflect.

lilactown03:05:42

Sounds like it’s not available through the usual ways

lilactown03:05:15

I’ve never needed to use super with React tbh

wilkerlucio03:05:05

its starting to feel like maybe CLJS should provide some way to generate actual class code, I'm seeing a lot of movement in that direction in JS and some libraries are starting to depend on that, it sucks but without that they seem to start getting out of reach =/

lilactown03:05:53

Yeah definitely

wilkerlucio03:05:56

I was able to kind of bypass that by writing constructor helpers in JS and using those functions to generate the classes, but quite bad and limited, I have to write one new helper for each new class I want to extend

wilkerlucio03:05:00

export function defineControl(f) {
  return class extends Rete.Control {
    constructor(key, ...args) {
      super(key);
      f.apply(this, [key, ...args]);
    }
  }
}

export function defineComponent(name, f) {
  return class extends Rete.Component {
    constructor(...args) {
      super(name);
      f.apply(this, args);
    }
  }
}

lilactown03:05:43

Yeah would probably be worth opening a ticket in jira and / or bringing it up in #cljs-dev

✔️ 4
lilactown04:05:59

It looks like the trick is to use ‘Reflect.construct’ for now

lilactown04:05:17

Hope your app only needs to work in modern browsers

wilkerlucio04:05:47

yeah, luckily I can count on that in this case 🙂

wilkerlucio04:05:21

and thanks for pointing that out

lilactown04:05:36

That Rete library looks pretty cool

lilactown04:05:22

That might be useful for a project idea I have... 😁

wilkerlucio04:05:36

hehhe, glad you got something out of this 🙂

wilkerlucio04:05:07

yeah, I find quite powerful the ways these node editors are used in 3d engines (for shading composition)

lilactown04:05:19

It’s pretty impressive

lilactown04:05:01

The least you can say is there is a lot of people hours living on NPM 😂

wilkerlucio04:05:52

I just tried using Reflect.construct, even that doesn't do the trick =/

wilkerlucio04:05:22

seems like its more a helper to call a regular fn as if it was calling no new, but fails to calls actual class constructors

rnandan27305:05:01

Any pointers to React VR via clojurescript

tomaas11:05:47

hi, how do select an item of js array this returns? aget does not work.

Roman Liutikov11:05:46

querySelector returns a single element

Roman Liutikov11:05:15

if you meant querySelectorAll which returns array-like, then you’d need to convert it into array or seq first

Roman Liutikov11:05:42

(-> array-like array-seq (nth 2))

thheller11:05:02

just use aget on the result of .querySelectorAll directly. only need to wrap it if you want other seq functions

Roman Liutikov11:05:00

I guess aget is not safe or recommended, isn’t it?

dominicm11:05:29

aget is fine for arrays

tianshu11:05:46

where can I find the document of how to write a cljs.edn in classpath?

tomaas11:05:33

thank, i missing all in querySelector

Roman Liutikov11:05:17

ah right, that recommendation was for aget + objects

tianshu11:05:54

the homepage for clojurescript looks a little messy. what information useful(about how to use features) is located at NEWS. I can just found some old stuff under REFERENCE and GUIDES.

tianshu12:05:37

I can't say what's wrong.

tianshu12:05:12

If I'm new to ClojureScript, just finished reading the startup. I have cljs.main, then I want to configure the production build. Then I go to REFERENCE, nothing useful I can find here. Then TOOLS, find some code, but for leiningen.

Roman Liutikov12:05:01

Quick Start guide is using cljs.main and has a section on production builds https://clojurescript.org/guides/quick-start is that what you are looking for?

tianshu12:05:29

yes, it has a section. but what if I want to provide some configuration via xxx.edn.

tianshu12:05:08

I may write script to do that, but according to https://github.com/pesterhazy/cljs-spa-example I think I can provide some edns for each build. so I want to find the document on http://clojurescript.org.

Roman Liutikov12:05:01

ok, so the example above is not using cljs.main directly, if you looks into dev script you’ll see that it runs figwheel.main

tianshu12:05:00

yes, I find it build with the figwheel-main

tianshu12:05:41

does cljs.main has support like this? or there's only the command line way?

Roman Liutikov13:05:18

yes cljs.main can consume edn config with --compile-opts flag, try clj -m cljs.main --help

tianshu13:05:17

let me try

tianshu13:05:28

Yes, I can use the -co. thanks for the help! @roman01la

lilactown15:05:04

isn’t there a website where I can type some CLJS and it will show me the JS output live?

mhuebert17:05:05

Maria.cloud also has a top-level js-source form for this purpose. (It was recently added - previously you had to issue a command to do this.) Example: https://www.maria.cloud/gist/a4594f54aada18ff48edef61902d4e1b?eval=true

lilactown17:05:58

😄 awesome!

dpsutton15:05:33

i remember seeing one on reddit a few years back

lilactown15:05:32

yeah, I was struggling to find the site it was on: http://blog.klipse.tech/clojure/2016/03/17/klipse.html

Roman Liutikov15:05:57

I’m often using this one http://app.klipse.tech/

🎉 12
mhuebert17:05:05

Maria.cloud also has a top-level js-source form for this purpose. (It was recently added - previously you had to issue a command to do this.) Example: https://www.maria.cloud/gist/a4594f54aada18ff48edef61902d4e1b?eval=true

thheller17:05:27

always be aware that compiler options may affect the code that gets generated. so code compiled this way may not match actual production code.

thelittlesipper20:05:47

I'm trying out devcards, and I am able to create cards and display them successfully. But, when I try and display a react component, it doesn't play very nicely. The naive approach I took was to do this:

(defcard simple-carbon-button
         "Simple carbon button"
         (sab/html
           [:> Button {} "TEST"]))
But, that throws an Uncaught Invariant Violation error. What is the correct way to display react components in devcards?

thelittlesipper20:05:19

As an aside, I am requiring the Button component, and it renders just fine with an r/render.

lilactown20:05:42

@sansaripour I’m not sure that [:> Button {} "TEST"] is valid for sablono

lilactown20:05:00

I think that’s specific to reagent

thelittlesipper20:05:34

I see. Any ideas on how I should go about rendering that react component within the devcard?

lilactown20:05:56

it sounds like you’re using reagent in this application yes?

lilactown21:05:32

you can use reagent to convert hiccup to React elements: (reagent.core/as-element [:div "foo"])

lilactown21:05:49

or in this case, (r/as-element [:> Button {} "TEST"])

💯 4
thelittlesipper21:05:51

that did the trick

grounded_sage22:05:47

Can someone please point me to the project/language that lets you use cljs by just dropping a script tag. I remember seeing it shared on numerous occasions but can’t remember what it was called.

grounded_sage22:05:30

I just remembered by asking haha