Fork me on GitHub
#shadow-cljs
<
2018-05-24
>
thheller08:05:07

@wilkerlucio style question. which would you prefer?

{:something 1
 :chrome/options {:matches [""]
                  :run-at "document_idle"}}


{:chrome/matches [""]
 :chrome/run-at "document_idle"
 :something 1}

thheller08:05:27

or I guess I could as anyone. I'm sort of undecided on which style to use. lots of nested maps or namespaced keys. Other potential candidates :compiler-options, :js-options etc.

mitchelkuijpers11:05:51

I am always for namespaced keys make stuff way easier and then you can spec it

thheller11:05:34

I prefer it for maybe one or two keys with the same ns. after that I prefer a nested map.

thheller11:05:26

@timovanderkamp do you use emacs+cider as well or standalone?

fatihict13:05:06

I run into this issue as well with shadow 2.3.23, without emacs but with cider/cider-nrepl

hlolli13:05:07

I'm hitting this error browser.cljs:39 Uncaught TypeError: Cannot read property 'written' of undefined useing

shadow-cljs.edn  cli version: 2.3.23  node: v9.6.1
tried deleteing target, this is a website I did few months back, and I updated shadow-cljs, and now can't see my changes stacktrace
browser.cljs:39 Uncaught TypeError: Cannot read property 'written' of undefined
    at Object.shadow$cljs$devtools$client$browser$goog_is_loaded_QMARK_ [as goog_is_loaded_QMARK_] (browser.cljs:39)
    at shadow$cljs$devtools$client$browser$src_is_loaded_QMARK_ (browser.cljs:48)
    at Function.G__35120__1 [as cljs$core$IFn$_invoke$arity$1] (core.cljs:4222)
    at cljs.core.filter.cljs$core$IFn$_invoke$arity$2 (core.cljs:5124)
    at cljs.core.LazySeq.sval (core.cljs:3394)
    at cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1 (core.cljs:3452)
    at Object.cljs$core$seq [as seq] (core.cljs:1210)
    at Function.cljs.core.seq_reduce.cljs$core$IFn$_invoke$arity$3 (core.cljs:2445)
    at cljs.core.LazySeq.cljs$core$IReduce$_reduce$arity$3 (core.cljs:3458)
    at Function.cljs.core.reduce.cljs$core$IFn$_invoke$arity$3 (core.cljs:2517)

hlolli14:05:14

forget that 😛 haha, just needed to clear cache

thheller14:05:59

which cache?

hlolli14:05:06

browser cache

hlolli14:05:35

chrome's "Empty Cache and Hard reload"

thheller14:05:36

hmm ok, seems odd that you only partially get the newer version though.

wilkerlucio14:05:13

@thheller I tend to prefer flat maps over nested ones, I found they usually simpler to deal with (only have to know one key instead of a path), so I like the one with namespaces better

dominicm15:05:42

I'm trying to get om/brutha working with React. With both [email protected] and [email protected], I'm getting TypeError: React.DOM.p is undefined. I'm using shadow-cljsjs.

dominicm15:05:55

is this a known issue?

jjttjj15:05:32

I'm trying to get play-cljs (https://github.com/oakes/play-cljs) working with shadow-cljs. It seems it bundles its own JavaScript source in their code (rather than using an external dependency) for the library p5.js, and then require it with:

(:require [goog.events :as events]
            [p5.core]
            [p5.tiled-map]
            ...
When I try to compile this with shadow-cljs I get
The required namespace "p5.core" is not available, it was required by "play_cljs/core.cljs".
Is there a way to make this work? (edit: I have already installed p5 in my project with npm)

dominicm15:05:53

Fixed mine, apparently the latest version in the om readme is not the latest

jjttjj15:05:47

I think my issue is that play-cljs uses foreign libs which is unsupported by shadow

thheller15:05:13

@dominicm was it fixed in om? the React.DOM stuff has been deprecated for a while.

thheller15:05:04

@jjttjj someone successfully used play-cljs with shadow-cljs but I forgot how exactly. typically you'll just need to install p5 via npm and create a shim file ala https://shadow-cljs.github.io/docs/UsersGuide.html#cljsjs

thheller15:05:22

@escherize can you share your p5/play-cljs setup?

kurt-o-sys19:05:53

Rather fundamental question of how to use npm-libs with shadow-cljs. I can import them properly, but I fail to get this to work: https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/getting-started.html#your-first-table More specifically, how translate this line to cljs:

export default () =>
  <BootstrapTable keyField='id' data={ products } columns={ columns } />

kurt-o-sys19:05:34

I can't seem to use [:> BootstrapTable {:data (clj->js content) :keyField "id"}]] or [BootstrapTable {:data (clj->js content) :keyField "id"}]]

kurt-o-sys19:05:06

reason: Cannot call a class as a function

kurt-o-sys19:05:49

I've got this require: ["react-bootstrap-table-next" :default BootstrapTable]

kurt-o-sys19:05:14

hmmm... missing something. not sure what yet.

kurt-o-sys19:05:34

d'you mind sharing the cljs code? (how d'you use BootstrapTable?

justinlee19:05:29

that code snippet is basically complete. the only thing missing is

(defn start []
  (js/console.log "Starting...")
  (r/render [app]
            (.getElementById js/document "app")))

(defn ^:export init []
  (start))

kurt-o-sys19:05:34

naa, that part is ok.

kurt-o-sys19:05:43

I'm struggling with the table.

justinlee19:05:31

i mean you literally have a code complete example. i just cloned reagent-shadow-cljs-starter, did a yarn add, and bam it works

justinlee19:05:23

by the way, i note that you didn’t supply the :columns key above

kurt-o-sys19:05:13

nope, I didn't...

kurt-o-sys19:05:23

let me try 😛

thheller19:05:43

@kurt-o-sys which version are you using? there was a bug in the closure compiler that was fixed only recently. https://github.com/google/closure-compiler/issues/2822

kurt-o-sys19:05:32

version of? cljs?

kurt-o-sys19:05:04

[thheller/shadow-cljs "2.3.21"] [org.clojure/clojurescript "1.10.238" :scope "provided"]

kurt-o-sys19:05:50

(well, shadow-cljs, but with :lein true)

thheller19:05:11

can you run lein deps :tree and see which com.google.javascript/closure-compiler-unshaded version you get?

kurt-o-sys19:05:43

[com.google.javascript/closure-compiler-unshaded "v20180319"]

kurt-o-sys19:05:49

but I may be getting there.

thheller19:05:01

try adding [com.google.javascript/closure-compiler-unshaded "v20180506"]

kurt-o-sys19:05:11

May be related to the table being loaded twice (for some reason), first time with empty data.

kurt-o-sys19:05:14

ok, will check.

thheller19:05:38

it might not be related to the version issue but the error looks familiar

thheller19:05:28

not sure why you are getting the old version though since the shadow-cljs version you have already depends on the newer on

thheller19:05:40

but for some reason the "older" version of cljs gets picked up first

kurt-o-sys19:05:59

updated the shadow-cljs version to 2.3.23 now.

kurt-o-sys19:05:42

which gives me the new version of the closure-compiler.

thheller19:05:22

ah ok. thought .21 already had the upgraded version but guess not

kurt-o-sys19:05:50

yeah, upgrading seems to help! thx a lot!!

nijk19:05:37

Does anyone know if it is possible to define deps on a per-build basis in shadow-cljs.edn?

thheller19:05:04

@nick828 hi! no that is not possible as its typically not useful to do this for CLJS. it is perfectly fine to always have devcards on the classpath as your build config defines what ends up in your build. not the classpath.

nijk20:05:46

ah ok, so let’s say I wanted to ‘accidentally’ add devcards to my :app bundle… What would I have to do?

thheller20:05:40

your namespaces decide what ends up in a build. so if none of your namespaces requires devcards.core then it will not be included.

thheller20:05:04

if you "accidentally" want to you (:require [devcards.core ...])

nijk20:05:48

cool, thought so - but I just wanted to double check. I’m much more familiar with JS than cljs and I think this is analogous to tree-shaking

thheller20:05:40

not really. tree shaking also only optimizes the code you actually use. you could have thousands of npm packages installed but it would not matter to your build unless you require them all

nijk20:05:26

ok, I’m with you

thheller20:05:02

but you can use deps.edn or lein to still do it if you really want to

nijk20:05:31

Just out of interest could you point to an example of how this might look? I’m using deps.edn to define those aliases in the screenshot above

thheller20:05:57

shadow-cljs -A:some-alias compile the-build

thheller20:05:12

only works when not connecting to a server though

thheller20:05:16

clj -A:x -m shadow.cljs.devtools.cli compile the-build

thheller20:05:37

no need to use shadow-cljs directly. clj works just fine too. just a tiny bit more to type out

nijk20:05:47

Thanks Thomas 🙂 I’m really enjoying using Shadow-cljs as a front-end dev it’s far better than the alternatives I’ve been exposed to in the cljs eco-system

thheller20:05:04

thanks 🙂

kurt-o-sys20:05:22

new 'translation' question: https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/filter-props.html#how-to-use

(ns ...
  (:require 
            ["react-bootstrap-table-next" :default BootstrapTable]
            ["react-bootstrap-table2-filter" :refer [textFilter] :default filterFactory]))

(defn generate-columns [fields]
  (map (fn [[fieldname title props]]
         (merge {:dataField fieldname
                 :text title}
                props)) fields))


  (let [
        columns (generate-columns
                 [["name" (i18n [:general/name]) {...
                                                  :filter  (textFilter) )}]
                  ["email" (i18n [:general/email]) {...}]])]
    [:div [:> BootstrapTable {:data          ...
                              :keyField      "id"
                              :filterFactory (filterFactory)
                              :columns       columns}]]))
shows the filter, properties to set work fine, but when I start to type (and hence, the filter should start):
text.js:102 Uncaught TypeError: c.props.onFilter is not a function
    at text.js:102

thheller20:05:00

guessing you are supposed to pass a :onFilter prop somewhere

thheller20:05:34

why the "generate-columns" fn?

thheller20:05:23

seems easier to just

(def columns
  (-> [{:dataField "id"
        :text "Product ID"}
       {:dataField "name"
        :text "Product Name"
        :filter (textFilter)}
       {:dataField "price"
        :text "Product Price"
        :filter (textFilter)}]
      (clj->js)))

kurt-o-sys20:05:25

oh, to generate the columns more easily.

kurt-o-sys20:05:02

there's always that datafield and text, so I just provide them as vectors.

thheller20:05:03

I think ultimately you end up with a lot more code going the generate-columns route

thheller20:05:28

but from what I can gather you probably just miss a (clj->js columns)

kurt-o-sys20:05:32

depends on how many fields you have and how many tables 😛

kurt-o-sys20:05:41

yeah, trying with clj->js

thheller20:05:42

not sure how reagent deals with transforming nested values

thheller20:05:18

so you are probably passing a CLJS vector to the react component which expects a JS array

justinlee20:05:21

@kurt-o-sys the syntax is :filter (filterFactory) not :filterFactory (filterFactory)

kurt-o-sys20:05:33

must be getting late... need to get some sleep.

kurt-o-sys20:05:46

thx a lot again! (I love shadow-cljs, I love the community, ... I'm full of love this evening :p)

❤️ 4
justinlee20:05:29

how i miss the amazing error checking of libraries like react-dnd, which would have caught that and given you nice error message. a really good and easy to use map validator would save the world so much grief. i had high hopes for schema and spec but they’re not quite there.

thheller20:05:40

pretty sure schema/spec wouldn't help with this JS component though 😉

kurt-o-sys21:05:55

well, I could've caught that there was a 'wrong' key.

justinlee21:05:19

I mean, generally, I wish this existed. I had high hopes for a lisp-based language having good tools in this department, which is one of the reasons why I got excited about cljs. Actually in JS, if you have typescript or flowtype going, these problems get caught at compile time. It’s not there yet, but it could be some day. 🙂 Still the best error checking seems to come from the facebook people who have a bunch of ad hoc checking built in.

thheller21:05:17

again: this assumes that the JS component is written in flow or typescript. if its not you gain nothing.

thheller21:05:43

and the propTypes checks are done by react anyways so the JS components could add them easily

justinlee21:05:48

well with flowtype third parties can type it. there’s a sideband project to provide types for libraries

thheller21:05:08

third parties could also spec/schema it, that is not a good argument 🙂

justinlee21:05:38

neither spec or schema give ergonomic error messages

justinlee21:05:55

and spec doesn’t even let you do closed maps without shenanigans

thheller21:05:58

it is "ok" with something like expound, but yeah they could be improved

thheller21:05:37

spec doesn't let you do closed maps. writing a spec for closed maps however is easy

justinlee21:05:17

for example, you should be able to type the shadow-cljs.edn such that if you misplace a key like :after-load, it should be able to give you a super high quality error message

justinlee21:05:47

spec doesn’t check for closed maps, which is a top form of error I’d like to catch

thheller21:05:09

(s/def ::y (map-spec :req {:foo string?} :closed? true))

  (s/explain ::y {:foo "1" :x 1})

justinlee21:05:28

oh i didn’t know you could do that

thheller21:05:26

extending spec is definitely possible but a bit cumbersome due to the macro-heavy implementation

justinlee21:05:34

oh you’ve done some wizardry here.

justinlee21:05:48

okay, NORMAL programmers like me can’t do that 🙂

thheller21:05:58

so definitely not recommended and I generally agree with the design decision done by spec regarding open maps

thheller21:05:11

but yeah in case on config files that is not ideal

justinlee21:05:56

spec makes hard stuff possible but it doesn’t make simple stuff easy

thheller21:05:09

@bhauman also did some impressive stuff in figwheel regarding the config validation, which could probably be turned into a really good library given unlimited time 😉

thheller21:05:28

someone just has to write all this stuff

justinlee21:05:29

i’ve heard about that but haven’t checked it out since i’m on the shadow train

thheller22:05:32

@wilkerlucio I'm beginning to question the viability of my :chrome-extension support. I extended it to support other scenarios like page/browser actions and it all works ok enough but has some drawbacks. might just end up recommending using a separate build for the extreme edge cases

wilkerlucio22:05:44

yeah, I think the current support is good already, I don't mind having multiple builds for (I already do with the devtool), I think its to contemplate the main cases, and leave the rest out

wilkerlucio22:05:35

the main issue IMO is the leak of repl support between builds, but that's not a specific problem of chrome target I guess (more related to modules in general)

thheller22:05:37

well the REPL has the same problem for every build that you open in multiple runtimes, eg. opening a browser build in chrome+firefox

thheller22:05:54

react-native running android/ios side by side and so on

thheller22:05:14

so that should be solved either way but sadly no editor is currently setup to do this