Fork me on GitHub
#clojurescript
<
2021-10-19
>
Richard Bowen01:10:11

Hey, what's your preferred way of implementing user authentication in Clojure and/or ClojureScript.

lsenjov03:10:58

For Clj we use buddy, which has served us pretty well

bbss06:10:03

I like firebase.

Stefan06:10:59

Good morning! I have a question about the state of affairs regarding externs inference. In the docs I’m reading that aget should only be used for arrays, not objects. There is also the library cljs-oops which provides an oget. It refers to the cljs docs about externs inference, noting: > Externs inference is very recent feature and looks promising. That comment was written a few years ago. So my question is: what should I use nowadays for accessing JS objects? Is externs inference good enough that I don’t need to worry about anything? Should I use cljs-oops? Any insight is much appreciated!

Stefan06:10:16

Please note that I have been mostly doing Clojure development, so I’m not too familiar with the exact differences between Clojure and ClojureScript.

lsenjov06:10:11

We currently use oops, gets the job done well (also it’s a nice api)

Stefan07:10:39

Oh and actually now that I think of it: do I also need this when using shadow-cljs?

thheller07:10:19

my advice is to never use cljs-oops

1
thheller07:10:45

when working with data (eg. json) use goog.object/get

thheller07:10:18

when working with code use regular interop and let extern inference to its thing, which just means you sometimes need to provide ^js hints on things that are JS objects

Stefan10:10:27

Thanks for your insights! I’m removing the cljs-oops dependency :)

lsenjov11:10:33

Is there a way to catch possible instances of items which might need to get type hinted? We’re using oops because we had too many cases of externs not being caught

henryw37413:10:44

there is *warn-on-infer* described here: https://clojurescript.org/guides/externs which will print WARNING: Cannot infer target type in expression ..

👍 1
henryw37413:10:47

I think there is some way to make specific warnings fail the build... or maybe that's in discussion still I can't remember

thheller14:10:23

in shadow-cljs it is default to warn for all of your sources. the default otherwise is only to warn if enabled, so if you are not using shadow-cljs and have not enabled warnings manually then you get no warnings at all

thheller14:10:41

inference still happens but will likely be incomplete due to those missing js hints

👍 1
maverick12:10:31

How can we add a tooltip for the input field when it is disabled?

p-himik13:10:29

IIRC the least invasive solution is to have a fully transparent div on top of it with that tooltip.

maverick09:10:13

Thanks @U2FRKM4TW I have used bootstrap data-toggle ="tooltip"

Simon15:10:27

Can i use a macro or something to generalize my usage of icons here:

(ns app.components.icons.icons
  (:require ["@tabler/icons" :refer (IconPlaneDeparture)]))

(defn icon-plane-departure []
  (r/as-element [:> IconPlaneDeparture
                 {:color "#6a35ff"
                  :stroke 1.25
                  :size 24}]))

(defn tabler-icon [name]
  (r/as-element [:> name {:color "#6a35ff"
                          :stroke 1.25
                          :size 24}]))

Simon15:10:19

I want to be able to use something like (tabler-icon "IconPlaneDeparture")

lilactown15:10:31

you’ll need to require all of the icons you want to use no matter what

lilactown15:10:50

macros used outside of ns can’t add requires in production

lilactown15:10:57

but you could add a map of strings->components and then use tabler-icon like [tabler-icon “IconPlaneDeparture”]

Simon15:10:27

What if i do something like this:

(ns app.components.icons.icons
  (:require [reagent.core :as r]
            ["@tabler/icons" :as tabler-icons]))

(defn tabler-icon [name]
  (r/as-element [:> tabler-icons/name {:color "#6a35ff"
                                       :stroke 1.25
                                       :size 24}]))

Simon15:10:01

The only problem is that the parameter name can't be used. I wonder if I could do it with a macro?

Simon16:10:50

Found this from stackoverflow https://stackoverflow.com/questions/2966014/how-do-i-create-a-macro-to-define-two-functions-in-clojure

; given a function name, its args and body, create 2 versions:
; ie (double-it foo [] ) should create 2 functions: foo and foo*
(defmacro double-it                
  [fname args & body]         
  `(do (defn ~fname ~args [email protected])
       (defn ~(symbol (str fname "*")) ~args [email protected])))

(double-it afunc [str] (println str))

(afunc* "asd")
(afunc "asd")

Simon16:10:13

Here they create a function name from a string using symbol

Simon16:10:18

@U4YGF4NGM Wherein lies the limitation?

lilactown16:10:40

the stackoverflow you posted is different than what I thought you were talking about

lilactown17:10:46

let me be clear what I'm saying you can't do: you can't have a function or a macro which allows other namespaces to dynamically refer or require things for you.

lilactown17:10:02

in ClojureScript, at least. Clojure is different

Simon17:10:50

If i allow myself to require all of the icons, would it then be possible?

lilactown17:10:29

there's a lot you could do but I'm going to cut to: I think your best bet is to require the icons and use a macro to generate the various functions you want to use

Simon17:10:35

What functions do you mean?

lilactown17:10:47

this generates a bunch of macros (but could be functions) like input, div, etc. to cut down all the boilerplate

lilactown17:10:11

then you can refer helix.dom/div helix.dom/input etc.

lilactown17:10:56

you can create a macro to generate the icon-plane-departure fn in your original post and any other icons you need

lilactown17:10:06

the limitation you're working around is that a namespace needs to refer to anything that's going to be used in it, so that it's statically analyzable, so that the clojurescript and google closure compiler emits the correct code

lilactown17:10:44

this is different than Clojure, which includes the compiler with your program. ClojureScript does not, so it has to do everything ahead of time, which means we're restricted more on how dynamic we can be

1
Simon17:10:16

This doens't work:

(defmacro tabler-icon-macro [name]
  `(r/as-element
    [:> ~(symbol (str "tabler-icons/" ~name))  ; <<<<<
     {:color "#6a35ff"
      :stroke 1.25
      :size 24}]))
while this does work:
(defmacro tabler-icon-macro [name]
  `(do
     (prn ~name)
     (r/as-element
      [:> ~(symbol (str "tabler-icons/" "IconPlaneDeparture"))  ; <<<<<
       {:color "#6a35ff"
        :stroke 1.25
        :size 24}])))
Does someone know why? The string printed for ~name is IconPlaneDeparture

lilactown18:10:35

how doesn't it work?

p-himik18:10:05

name resolves to a symbol. A symbol that's not bound. It should be passed quoted or turned into a string beforehand.

Benjamin15:10:28

Did anybody code a slack app / bot lately? How would you go about it? I have a small project and considered js but then I thought I use cljs if I have the chance. I'm thinking to basically use this https://github.com/slackapi/bolt-js-getting-started-app but use clojurescript

Simon17:10:16

This doens't work:

(defmacro tabler-icon-macro [name]
  `(r/as-element
    [:> ~(symbol (str "tabler-icons/" ~name))  ; <<<<<
     {:color "#6a35ff"
      :stroke 1.25
      :size 24}]))
while this does work:
(defmacro tabler-icon-macro [name]
  `(do
     (prn ~name)
     (r/as-element
      [:> ~(symbol (str "tabler-icons/" "IconPlaneDeparture"))  ; <<<<<
       {:color "#6a35ff"
        :stroke 1.25
        :size 24}])))
Does someone know why? The string printed for ~name is IconPlaneDeparture

manutter5117:10:17

Try it with name instead of ~name in the call to str.

thheller17:10:55

why do you want this to be a macro? I mean why do you do the r/as-element? but even without just make it a function and call it with (tabler-icon tabler/IconPlaneDepature) why write a macro only to skip passing in the tabler/ alias?

manutter5117:10:06

Ah yes, the first rule of Macro Club: Don’t use macros.

Simon17:10:33

The idea was that I could generalize the usage of icons instead of creating an icon function for every icon that I use.

thheller17:10:14

you don't have an icon function for every icon. you have one icon function and pass in the icon to use as an argument

Simon17:10:09

(defn icon-plane-departure []
  (r/as-element [tabler-icons/IconPlaneDeparture
                 {:color "#6a35ff"
                  :stroke 1.25
                  :size 24}]))

Simon17:10:04

This is for n=1 icon. But I thought it would be cumbersome to have to write something like that for every icon I wanted to use.

thheller18:10:34

(defn small-icon [the-icon-to-use]
  (r/as-element [:> the-icon-to-use
                 {:color "#6a35ff"
                  :stroke 1.25
                  :size 24}]))

(small-icon tabler-icons/Thing)
(small-icon tabler-icons/ThatOtherIcon)

Simon18:10:29

Is there a way to do that without prepending tabler-icons?

Simon18:10:09

e.g. (small-icon ThatOtherIcon)

thheller18:10:12

either :refer them in the require or make the alias shorter. otherwise no but I also don't see a problem with that 😛

thheller18:10:56

:as i then i/Thing

🙌 1
Simon18:10:48

Okay Thank you. I think i have over engineered that one 😅 Defintely don't need a macro. But in theory would it be possible to do that part with a macro?

Simon18:10:11

so that one wouldn't need to prepend it.

thheller18:10:44

not really practically speaking. you can do it but it'll be much more clunky and annoying

🙏 1
Simon18:10:46

Thank you anyways, you just saved me from diving deeper into the rabbit hole. Although now i know how to possibly use a macro another time 😄

lilactown18:10:20

I've been trying to help in this original thread: https://clojurians.slack.com/archives/C03S1L9DN/p1634658147275100 correct me if i'm wrong thheller

👍 1
thheller18:10:18

you can go with a macro that sets up a namespace with all the icons from the package. I wouldn't recommend doing that but you can.

dnolen20:10:50

ClojureScript master now has a new flag - :global-goog-object&array - intentionally ugly name - to get the old behavior where a library could assume goog.object or goog.array would be present

dnolen20:10:28

please update your libraries and your macros to stop making this assumption - for apps just use the flag to avoid problems until libraries bump

Alex Miller (Clojure team)20:10:37

mmm... syntactic vinegar

😆 32