Reputation: 2364
I'm a newbie with CojureScript because I got the LISP itch some months ago and then I migrated the API to Clojure and I'm loving it. Now I want to migrate the frontend too but this is my first week with CLJS.
So, I have this function:
(defn foo []
(events/listen (gdom/getElement "icon-add") EventType.CLICK
(fn [e] (.log js/console (str ">>> VALUE >>>>> " e)))))
the function works great in the core.cljs file, but if I move it to users.cljs file and I call it from the core namespace with:
(ns zentaur.core
(:require [zentaur.users :as users]
(users/foo)
the DOM element "icon-add" is never found and instead I get the error message:
Uncaught goog.asserts.AssertionError {message: "Assertion failed: Listener can not be null.", reportErrorToServer: true,
in the browser console. If I move the function back to core.cljs, all works fine again. Then my question is: how can I move a function to another NS and be sure it keeps working?
UPDATE:
I noted that if I call the listener directly in users.cljs:
(events/listen (gdom/getElement "icon-add") EventType.CLICK
(fn [] (.log js/console (str ">>> events/listen in users ns"))))
(I mean out of any function), all works fine, the code find the DOM element.
SECOND UPDATE
Thanks a lot for your answers but this issue looks like a "compiling time" problem. All the listeners:
(events/listen (gdom/getElement "icon-add") EventType.CLICK foo-funct)
must be loaded when CLJS runs at first time. Loading another ns is a "second time" thing and then the DOM is not reachable anymore.
Upvotes: 2
Views: 1648
Reputation: 6509
The user namespace is special in that it is designed to be pre-loaded, and for development only. It is also the only time you will ever see a namespace that does not have a parent package. I say this just to warn you off using user
as a namespace name - doing so will just cause confusion - whether it has a parent package or not.
Your problem seems to be that one of the arguments to events/listen
is somehow returning nil
. Do you have gdom
as a require in zentaur.users
, so: [goog.dom :as gdom]
?
Upvotes: 3
Reputation: 1372
Google Closure library throws the assertion error because your listener function, i.e., the third parameter to listen
is null
.
Looking at the source code for the library, it tries to wrap the third parameter into a Listener
, and the error string is produced from this failed assertion for a truthy value.
I often have similar problem, when I accidentally put extra parenthesis around the function. In effect, this leads to the function being called immediately after its declaration. This may happen without warning, even when your declared function requires one or more parameters; ClojureScript runs on JS, which does not check the arity when calling the function. Since the body of your listener is just console.log
, which returns null
, you would be trying to assign the null
as listener.
You did note that the code example that you give is working in core.cljs
. Indeed, the example does not show any obvious reason why the function is null in this case. Perhaps there was a small error in copy-pasting this function to users.cljs
, e.g., extra parenthesis added?
Upvotes: 2
Reputation: 29984
In the core namespace you need to require
the 2nd namespace:
(ns xyz.core
(:require [xyz.users :as users] ))
(users/foo) ; call the function
This assumes your code is laid out as
src
src/xyz
src/xyz/core.cljs
src/xyz/users.cljs
There are also some good ideas here on various tradeoffs in naming and references to other namespaces.
Upvotes: 3