trouble in emitting <AgGridReact> , using clojurescript + Reagent + cljsjs/ag-grid-react - clojurescript

I'm trying to use React ag-grid in Reagent (ag-grid reference) , but having trouble in emitting node AgGridReact ,
Implemented React.Component using pesterhazy approach , but emitting AgGridReact from rendor method is not working. Please suggest a better way with hiccup syntax ,
I was checking something like this from the render method:
(def ag-adapter (reagent/adapt-react-class js/agGridReact))
[ag-adapter { columnDefs={somecols} rowData={somerowData}}]
FYI, I created the project using the command lein new reagent reagent-aggrid, and using lein figwheel grid reference [cljsjs/ag-grid-react "17.0.0-0"]
*********UPDATE :**
Got this resolved using below , sample reagent-aggrid
(def ag-adapter (reagent/adapt-react-class (.-AgGridReact js/agGridReact) ))

got this resolved using below , issue was with the way I referred ag grid
(def ag-adapter (reagent/adapt-react-class (.-AgGridReact js/agGridReact) ))

Related

CLJS: Setting a JS property to the result of calling a method on it

I'm looking to modify some existing text in a web app, which I'm accessing with expressions like this:
(.-innerHTML (.getElementById js/document "myElementId"))
What I specifically want to do is mutate that text via a search/replace:
(set! (^that whole thing) (.replace (^that whole thing) "old" "new"))
And I'd ideally like to do that without having to repeat the property-access expression. Is there any existing shortcut for this? I'm envisioning something like Raku's object .= method(args) shorthand for object = object.method(args); maybe a good clj name/pattern would be (.set! (access-expression) method & args). I can always write a macro, but was wondering if I'd overlooked something already there.
I was curious too and looked in the CLJS CheatSheet and they link to the CLJS Oops library which provides similarly looking functions.
It seems to be that the most robust solution would be to just rely on the Google Closure Library (which is always at hand) and use a combination of goog.object/get and goog.object/set (no need for a macro), something like:
(require 'goog.object)
(defn update-obj! [obj field f & args]
(let [old-val (goog.object/get obj field)
new-val (apply f old-val args)]
(goog.object/set obj field new-val)))
;; Example:
(update-obj! (.getElementById js/document "my-div") "innerHTML" (partial str "it works: "))
This should work in both development and optimized output.

Clojure/Clojurescript: Argument to resolve must be a quoted symbol

I'm attempting to use a string saved in a variable to call a function like so:
(defn update-product-list [] "Test")
(defn handle-state-change [action]
((resolve (symbol action))))
(handle-state-change "update-product-list")
However, this gives me the following error: Assert failed: Argument to resolve must be a quoted symbol
I've also tried changing the above line to:
((resolve (quote (symbol action))))
But this still gives an error. I also tried changing it just to:
((resolve 'action))
But this gives a different error I don't quite understand: js/action is shadowed by a local. I don't want to override the function just call it. Not sure where I'm going wrong. I've looked at a few examples, but can't see to pin it down.
ClojureScript supports :advanced optimization, in which Google Closure Compiler will rename, inline, or eliminate (unused) functions in order to implement minification. In short, the name of the function you want to look up will, in general, simply no longer exist under :advanced.
Because of this, ClojureScript's resolve is a compile-time facility (a macro requiring a literal quoted symbol).
If you are using :simple or self-hosted ClojureScript, more options are available to you because the support needed persists into runtime. For example Planck has a planck.core/resolve that behave's like Clojure's resolve. A similar approach is possible in Lumo, and similar facilities can be fashioned if using :simple.
In general though, given :advanced, if you need to map strings to a set of functions, you need to somehow arrange to have a static mapping constructed at compile time to support this (the set of functions must be known a priori, at compile time).
If you have a namespace (the name of which is statically known at compile time) which defines functions that need to be dynamically called via strings, you could consider making use of ns-publics:
cljs.user=> (ns foo.core)
foo.core=> (defn square [x] (* x x))
#'foo.core/square
foo.core=> (in-ns 'cljs.user)
nil
cljs.user=> (when-some [fn-var ((ns-publics 'foo.core) (symbol "square"))]
(fn-var 3))
9
This will work under :advanced. The mapping constructed by ns-publics is static; built at compile-time. If you have multiple namespaces that need such treatment, you could merge several calls to ns-publics to build a larger map.
The advantage of this approach is that the code involved is pretty short and requires little maintenance. The disadvantage is that it dumps all of the public vars of the namespace (foo.core in this example) into your generated code (and the generated code for vars is somewhat verbose). Another disadvantage is that you need to statically know the namespace(s) involved at compile time.
If you need to further minimize generated code size, you could just build / maintain a simple static map from string to function value as in
(def fns {"square" foo.core/square})
and use it appropriately, keeping it up to date as your codebase evolves.
Another option would be to mark the functions that you need to access using ^:export meta, and then to call those functions using JavaScript interop. For example if you define the function this way
(defn ^:export square [x] (* x x))
then you can use strings / interop to lookup the function and call it at runtime. Here's an example:
((goog.object/getValueByKeys js/window #js ["foo" "core" "square"]) 3)
The use of ^:export and :advanced is covered here. If you know that you are using :simple or less, then you can simply use JavaScript interop to call the functions of interest, without needn't to use ^:export.
Note that there is no general solution that would let you look up a function by name at runtime under :advanced without somehow putting some aspect of that function into your code at compile time. (In fact, if a function is not referenced in a way that Google Closure Compiler can statically, see, the function implementation will be completely eliminated as dead code.) In the above, ns-publics grabs all the vars for a namespace at compile time, rolling your own lookup map sets up static code to refer to the function value, and using ^:export statically arranges to make the name of the function persist into runtime.
You need to use it like this:
((resolve 'inc) 5)) => 6
or, deconstructed a bit:
(let [the-fn (resolve 'inc)]
(the-fn 7))
=> 8
If you have the function name as a string, use the symbol function to convert from string => symbol (from clojuredocs.org):
user=> ((-> "first" symbol resolve) [1 2 3])
1
And, never forget the Clojure CheatSheet!

Recursive Call with goog.dom.animationFrame

I am trying to use google closure animationFrame feature.
I would like to create an animation task with it and to call that created task recursively.
I defined a def named animationTask.
When I try to use that def recursively in that task it fails. It logs out that animationTask is undefined and thus can not be used as a function.
Could anyone point me in the right direction please?
I feel like I am missing some basic clojure knowledge here.
Your code is calling the animation task function before it is defined. It is analogous to this simpler code:
(defn create [x] (fn []))
(def task (create {:measure (task)}))
If you try that in a REPL, you'll see that task is being called while it is still undefined.
Instead, the value under :measure is supposed to be a function, and the API takes a JavaScript object. This would be analogous to revising the above example to be:
(def task (create #js {:measure (fn [state] (task))}))

Calling a function from another namespace in ClojureScript

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.
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.
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]?
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?

Clojure: re-export vars

Is there a way to re-export some namespace's vars from another namespace? I'd like to be able to do this:
(ns mine.core
(:use [incanter core charts datasets io]))
; re-export Incanter somehow
Then in the REPL I would be able to use Incanter's functions by just use-ing mine.core.
user=> (use 'mine.core)
nil
user=> (view (histogram (sample-normal 1000)))
Thanks!
I used to accomplish this by putting the commonly REPLd use expressions in a separate file that I can load-file when I start my REPL. This worked fairly well because I could put everything in there and then get at more than just one namespace.
Later I switched to defining an 'everything' namespace and starting my repl in that using leiningend :main directive like in this SO question which was like my first approach but seemed more elegant.
my ways continued to change and i now always switch to the namespace containing the code. This has worked well because on larger project It helps keep track of what code goes where and I think this practice helps me learn the layout of the code faster. Of course everyone's experiences are different and personal, YMMV :)
Try http://code.google.com/p/clj-nstools/
I suggest to consider importing all necessary dependencies explicitly as suggested in other answers. This usually leads to less complex code.
However if you do want this, e.g. to present a consistent interface, then you can do this with clojure.core/intern function that makes any symbol "native" to given namespace. For example:
(ns user)
(intern 'user 'map clojure.core/map)
(ns new-ns)
(require 'user)
(user/map inc [1 2 3])
; => [2 3 4]
(use 'user)
; => WARNING: map already refers to: #'clojure.core/map in namespace: new-ns,
; being replaced by: #'user/map
(map inc [1 2 3])
; => [2 3 4]
Note that changes in symbol's original namespace will not be reflected until you re-intern the symbol.