clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
Ronny Li 2020-11-02T01:26:57.457100Z

Hi I'm running into a circular dependency with reitit because my view is linking to another page, which requires the route but the route depends on the view. I imagine this is a common issue that beginners run into but does anyone have a simple code example I could follow for breaking the loop? Here's what I currently have:

;; component

(ns
  app.components
  (:require [reitit.frontend.easy :as rife]))

(defn card []
      [:div {:on-click #(rife/push-state ::card-details)}
       "Foo"])

(defn card-details []
    [:div "Bar"])

;; ================
(ns app.navbar
  (:require
    [app.components :as c]
    [reitit.frontend :as rif]
    [reitit.frontend.easy :as rife]))

(def routes
  [["/card"
    {:name ::card
     :view c/card}]

   ["/card-details"
    {:name ::card-details
     :view c/card-details}]])

Ronny Li 2020-11-02T14:51:03.009600Z

thank you so much! I was wondering what the :: convention meant...

Rahul P. 2020-11-02T03:00:09.458800Z

Hey all, I'm new to cljs and writing a search function for my users table. I am having difficulties accessing the value of my input element in my core.cljs

[:card_index_dividers:
    [:h4 "Search User: "]
    [:input {:id "searchKey"
	         :type "text"}]
    [:button {:id "searchButton"
              :onClick (fn [e]
                         (getUserByName "TODO Pass User name here"))}  "Search"]]
Can anyone help me or refer any specific guide or project?

phronmophobic 2020-11-02T03:07:33.459300Z

I would look into clojurescript interop with js. here's a primer I found that looks reasonable, https://lwhorton.github.io/2018/10/20/clojurescript-interop-with-javascript.html I don't have a cljs repl available, but I think the following should print the user name:

[:card_index_dividers:
 [:h4 "Search User: "]
 [:input {:id "searchKey"
	  :type "text"}]
 [:button.searchButton {:onClick (fn [e]
                                   (let [input (js/document.getElementById "searchKey")]
                                     (prn (.-value input))))}  "Search"]]

πŸ‘ 1
Ritchie Young 2020-11-02T03:41:17.459500Z

Even simpler:

[:card_index_dividers:
    [:h4 "Search User: "]
    [:input {:id "searchKey"
	         :type "text"}]
    [:button {:id "searchButton"
              :onClick (fn [e]
                         (getUserByName (-> e .-target .-value))}  "Search"]]

phronmophobic 2020-11-02T04:05:18.459800Z

wouldn't target be the button in this case?

Rahul P. 2020-11-02T04:11:02.460Z

@smith.adriane It gave me reading null value with your solution

core.cljs:280 Uncaught TypeError: Cannot read property 'value' of null
    at onClick (core.cljs:280)
    at Object.global.invokeGuardedCallback (ReactErrorUtils.js:71)
    at executeDispatch (EventPluginUtils.js:86)
    at Object.executeDispatchesInOrder (EventPluginUtils.js:109)
    at executeDispatchesAndRelease (EventPluginHub.js:44)
    at executeDispatchesAndReleaseTopLevel (EventPluginHub.js:55)
    at Array.forEach (<anonymous>)

phronmophobic 2020-11-02T04:13:22.460600Z

what happens if you type document.getElementById ("searchKey") into the js console?

phronmophobic 2020-11-02T04:14:29.460800Z

is the input not having it's id set for some reason?

Rahul P. 2020-11-02T04:15:19.461Z

My bad. The username I was passing had some white spaces. All Good now.

Rahul P. 2020-11-02T04:15:48.461300Z

Thanks for the help.

Ritchie Young 2020-11-02T06:05:41.461700Z

Ah, you’re right @smith.adriane. My bad.

p-himik 2020-11-02T06:22:45.461900Z

Your views do not require the routes - they require the keyword. Just use the full keyword name, without aliases, and you're good to go.

p-himik 2020-11-02T06:23:08.462100Z

In your particular code above, the only mistake that I can see is that you're using ::card-details in both NSs.

p-himik 2020-11-02T06:23:47.462500Z

Since :: gets substituted with the current NS, they end up being completely different keywords.

p-himik 2020-11-02T06:24:31.462700Z

So you should either spell out the full namespace in one of the usages or just switch to simple keywords without namespaces (assuming reitit allows you to do that).

tugh 2020-11-02T08:59:31.467400Z

i'm trying to set a var from another ns but i got no luck. here is what i'm trying:

(ns chatbot.flow.conversational.core)

(defn init []
  (set! 'chatbot.flow.views/test123 123))
here is the error from shadowcljs build logs:
--------------------------------------------------------------------------------
  11 | 
  12 | (defn init
  13 |   []
  14 |   (set! 'chatbot.flow.views/test123 123))
---------^----------------------------------------------------------------------
null
set! target must be a field or a symbol naming a var at line 14 chatbot/flow/conversational/core.cljs
init fn will be called after the module is loaded. i'm trying to hide the details of which components are in use. there will be different modules like conversational, form, etc. can someone point out what i'm missing? why i'm getting the above error even though i'm passing a symbol to set! ?

tugh 2020-11-02T09:01:20.468400Z

btw i'm not sure if this is the correct way of setting vars from different namespaces. if there are other approaches i'll be glad to know. thanks everyone πŸ™‚

thheller 2020-11-02T09:01:42.468700Z

you cannot "cheat" creating circular dependencies this way

thheller 2020-11-02T09:03:09.469600Z

your example is a bit too abstract to provide alternatives but basically you need one ns that can be shared anywhere that has a reference to an atom or so

thheller 2020-11-02T09:03:31.470100Z

I typically have a (ns my.app.env) (defonce my-global-state-ref (atom {})) which all other namespace can use to coordinate

tugh 2020-11-02T09:15:45.480100Z

thanks @thheller atoms would be ugly for my situation b/c i will set reagent view functions and i dont want to deref every time i want to use a view function. let me explain it in more detail: my re-frame app has 3 modules. core, conversational , form . core contains the logic and other parts just contain components. i simply want to render different components based on flow type. both conversational and form components will have the exact same names but will render different html. for example, both will have a component named user-input . the only difference of these views are the produced html. core module fetches the flow data from an API and loads the required module with shadow.loader/load. after loading the required module i don't want the core to know about which components are in use so i thought binding them to another namespace chatbot.flow.views can solve my problem. hope this gives you more insight about what i'm trying to achieve.

thheller 2020-11-02T09:17:51.480600Z

my use of atom does not mean that you actually have to use an atom

thheller 2020-11-02T09:18:09.481100Z

you can use (def a "foo") and in your module (set! env/a "bar") if you really have to

thheller 2020-11-02T09:18:35.481500Z

I'm not sure how you would build an app in core if that doesn't know what is happening

thheller 2020-11-02T09:20:30.482300Z

I would strongly recommend not using set! and instead have some of your state data reflect what it is supposed to do

πŸ‘ 1
thheller 2020-11-02T09:21:12.482500Z

as described here https://code.thheller.com/blog/shadow-cljs/2019/03/03/code-splitting-clojurescript.html

πŸ‘€ 1
tugh 2020-11-02T09:21:12.482600Z

so, do you mean that i should def it first in chatbot.flow.views and then bind(using set!) whatever i want from another namespace? is this why i'm getting the above error?

thheller 2020-11-02T09:21:41.482900Z

the error you are getting is that set! does not accept a quoted symbol

thheller 2020-11-02T09:22:32.483100Z

you can use set! if the namespace is properly required and aliased. doing that is most likely a code smell and something you should rarely do.

tugh 2020-11-02T09:32:40.484500Z

but this will break my code splitting. i will require chatbot.flow.views on all three modules

tugh 2020-11-02T09:35:48.485400Z

i will implement the events, subs, and other details inΒ `core`Β and component modules will use them. i basically want to decouple rendering details from core

2020-11-02T12:23:56.487500Z

I am getting "Error: Require clojure.test.check and clojure.test.check.properties before calling check." when trying to use cljs.spec.test.alpha/check but I have required [clojure.test.check] and [clojure.test.check.properties] already. What might I be doing wrong. I am using shadow-cljs.

thheller 2020-11-02T12:48:06.488Z

@mac make sure to require the CLJS variants and CLJ variants in the correct places. can't tell more from the error description but you are mixing clojure.test and cljs.spec which is confusing

2020-11-02T12:50:39.489400Z

@thheller I am requiring the following in a clsj namespace, is that wrong? If so what should I be requiring?

[clojure.test.check]
   [clojure.test.check.properties]
   [cljs.spec.alpha :as sa]
   [cljs.spec.test.alpha
    :refer-macros [instrument check]]

2020-11-02T12:53:12.490700Z

cljs.spec.test.alpha checks for the presence of clojure.test.check and clojure.test.check.properties

thheller 2020-11-02T12:59:16.491Z

sorry I can't answer that. the context of WHERE you are using this matters.

2020-11-02T13:01:57.492Z

@thheller I am using it in a cljs file. Is there further info regarding where I can provide?

thheller 2020-11-02T13:02:16.492200Z

the full stacktrace for example

2020-11-02T13:02:57.492700Z

@thheller There is no stacktrace, just the exception.

thheller 2020-11-02T13:03:45.493200Z

there always is a stacktrace πŸ˜›

thheller 2020-11-02T13:04:02.493500Z

when do you get the error? REPL?

2020-11-02T13:04:44.494200Z

When I call cljs.spec.test.alpha/check

thheller 2020-11-02T13:04:53.494400Z

HOW are you calling it?

thheller 2020-11-02T13:05:14.494900Z

I do not know what you are doing so please provide more context than just the error πŸ˜›

thheller 2020-11-02T13:05:44.495400Z

you are calling it from the REPL? you are calling it in a function when compiling?

thheller 2020-11-02T13:06:02.496Z

do you get the error in the shadow-cljs compile log?

2020-11-02T13:07:06.497200Z

I am calling it from emacs using Cider. There is no error in the compile log. I have shadow-cljs watch running and everything compiles.

2020-11-02T13:08:30.498300Z

This is the ful code.

(ns test 
 (:require
   [clojure.test.check]
   [clojure.test.check.properties]
   [cljs.spec.alpha :as sa]
   [cljs.spec.test.alpha
    :refer-macros [instrument check]]
   ))

(defn foo [])
(sa/fdef foo :args (sa/cat))
(instrument `foo)

(check `foo)

thheller 2020-11-02T13:10:31.499Z

works fine for me?

thheller 2020-11-02T13:10:35.499200Z

test=> (check `foo)
[{:spec #object[cljs.spec.alpha.t_cljs$spec$alpha77660], :clojure.spec.test.check/ret {:result true, :pass? true, :num-tests 1000, :time-elapsed-ms 137, :seed 1604322614082}, :sym test/foo}]

thheller 2020-11-02T13:12:36.499700Z

just did all the forms in shadow-cljs node-repl

thheller 2020-11-02T13:13:44.000500Z

can't comment on the emacs/cider bits much. I'm guessing it is maybe mixing CLJ and CLJS modes?

2020-11-02T13:14:29.000900Z

I get the below doing the same:

shadow-cljs node-repl
shadow-cljs - config: /home/mac/projects/hypercontracts/shadow-cljs.edn
shadow-cljs - connected to server

cljs.user=> shadow-cljs - #12 ready!

(ns test 
 (:require
   [clojure.test.check]
   [clojure.test.check.properties]
   [cljs.spec.alpha :as sa]
   [cljs.spec.test.alpha
    :refer-macros [instrument check]]
   ))
nil
test=> (defn foo [])
#'test/foo
test=> (sa/fdef foo :args (sa/cat))
test/foo
test=> (instrument `foo)
[test/foo]
test=> (check `foo)
#object[Error Error: Require clojure.test.check and clojure.test.check.properties before calling check.]
test=> 

thheller 2020-11-02T13:15:55.001900Z

odd. which version is this?

thheller 2020-11-02T13:16:48.002100Z

I have [org.clojure/test.check "1.1.0"]

2020-11-02T13:19:11.002700Z

@thheller this is output from shadow-cljs info in the project:

=== Version
jar:            2.11.5
cli:            2.11.5
deps:           1.3.2
config-version: 2.11.5

thheller 2020-11-02T13:19:44.003200Z

no I meant the dependency version

thheller 2020-11-02T13:19:55.003700Z

shadow-cljs version is fine

2020-11-02T13:20:07.003900Z

@thheller I have the same version of org.clojure/test.check

thheller 2020-11-02T13:22:54.004300Z

hmm not a clue. works fine on an empty test project.

thheller 2020-11-02T13:24:15.004700Z

did you try restarting the shadow-cljs process? maybe its just in some weird state.

2020-11-02T13:25:15.005Z

@thheller I can try again.

2020-11-02T13:30:43.005300Z

@thheller Made no difference.

2020-11-02T13:39:53.006600Z

@thheller I just spun up a new project and it works like it did for you. So I guess something in our current project is interfering somehow. But how to find what.

thheller 2020-11-02T13:43:10.006900Z

first instinct is always dependency conflicts

thheller 2020-11-02T13:43:34.007200Z

can't think of anything else making this fail

2020-11-02T13:55:06.008900Z

@thheller Yeah, I looked at shadow-cljs info. There is a primary dependency on [org.clojure/spec.alpha "0.2.176"] but that is not in shadow-cljs.edn.