Fork me on GitHub

Hello everyone, has anyone else tried using ag-grid-react with infinite scrolling? I can't figure out why it doesn't link up the rows correctly, it ends up drawing 100 empty rows that is scrollable. I'll try to shorten the data for your convinience:

(ns example (:require
             [reagent.core :as r]
             ["ag-grid-react" :as ag-grid :refer (AgGridReact)]
             [cljs-http.client :as http]
             [cljs.core.async :refer [<!]]))
(def ag-adapter (r/adapt-react-class AgGridReact))

(defn create-grid
  "I'm in a DIV somewhere, the actual grid component that the user interacts with"
  [ag-adapter {:gridOptions defaultGridOptions}])

(def defaultGridOptions {:rowModelType "infinite" ; if this is not defined, datasource with getRows won't work.
                         :columnDefs  col-data ; looks like it's drawing the columns up correctly
                         :datasource {:getRows get-rows}}) ; passes params to function correctly

(def col-data
     "This correctly creates a grid with "Id" and "Description" columns, even creates the filter options correctly, it seems to work"
     [{ :headerName "Id" :field "id" :filter "agNumberColumnFilter" }
      { :headerName "Description" :field "description" }

(defn get-rows [params]
  ;(prn params) ; Is a #js object with expected values filled in from ag-grid component
  (go (let [response (<! (http/post "valid-endpoint"
                                    {:with-credentials? false
                                     :json-params {
                                                   :startRow (goog.object/getValueByKeys params #js ["startRow"])
                                                   :endRow (goog.object/getValueByKeys params #js ["endRow"])
                                                   :filterModel (goog.object/getValueByKeys params #js ["filterModel"])
                                                   :sortModel (goog.object/getValueByKeys params #js ["sortModel"])}}))]
        ;(prn (:rows (:body response))) ; This prints expected data, albeit in clojure form (e.g. [{ :id 1 :description "some example" }] )
        (js-invoke params "successCallback" (:rows (:body response)) (:lastRow (:body response)))))) ; What I think this means in JS: params.successCallback(rows, lastRow)
Context: I am using an endpoint that I know returns the correct data for an ag-grid, I'm evaluating CLJS by trying to convert a small part of an existing app to work in it. More info: Scrolling in the component causes POST callbacks that return (seemingly) correct data in the console / network tab. (P.S. If I'm doing something in a stupid way, let me know.)


Are (:rows (:body response)) and (:lastRow (:body response)) plain JS objects? Because I would not expect successCallback to work with CLJS objects. Apart from that, you shouldn't use js-invoke for function names that are proper identifiers. Just use (.successCallback ^js params ...).


Thanks for the tip @U2FRKM4TW, yes the API returns a JSON object that looks something like this in the old app (TypeScript):

export interface ISomeGrid {
  lastRow: number;
  rows: ISomeData[]; // imagine it being of format { id: 1, description: "some description"} for this example
I tried "un-clojuring" the response by doing this:
(.stringify js/JSON (clj->js (:rows (:body response))))
But it doesn't seem to improve my situation, is there some better way to convert the response into JSON for this successCallback to consume?


Don't call stringify, just call (clj->js (:rows (:body response))). It would be even better if you could tell cljs-http to stop automatically converting JS objects into CLJ data.

👍 3

To complete this answer for possible future readers, this was the missing piece of the puzzle and it ended up working perfectly when I had time to try it today (although as stated above, it would be even better to return the correct data response directly):

(.successCallback ^js params (clj->js (:rows (:body response))) (clj->js (:lastRow (:body response)))))))
For reference, the above ag-grid call is equivalent to this in JS:
params.successCallback(rows, lastRow);
Thanks again, @U2FRKM4TW!


And if no one has used ag-grid-react in this way before-> then without knowledge of its API, can you see if I'm doing something dumb in get-rows?


Hello there, does anybody know how to use ANT design subcomponents in Reagent? For example, in javascript I'd import subcomponents like this:

import { Layout, Menu, Breadcrumb } from 'antd';

const { Header, Content, Footer } = Layout;
and then I could use them like this: <Header /> The parent component (Layout) works fine, but I can't manage to use the subcomponents. I tried [:> Layout.Header ] but it doesn't work.


I also tried to destructure the subcomponents in a let binding like this:

(defn authenticated
  (let [{Header :Header} Layout]
    (js/console.log Header)
    [:> Layout
     [:> Header
      [:Menu {:theme               "dark"
              :mode                "horizontal"
              :defaultSelectedKeys ["1"]}
       ;[:Menu.Item {:key "1"} "nav 1"]
       ;[:Menu.Item {:key "2"} "nav 2"]
       ;[:Menu.Item {:key "3"} "nav 3"]
     [:> Layout.Content
      [:h1 "Main Content"]]
     [:> Layout.Footer
      [:p "Footer"]]
but no success


The issue is in your let. Layout is a JS object, you cannot destructure it.


I'm also not sure what those :Menu and :Menu.Item are. They're keywords and I don't think they're valid (or at least regular) HTML tags.


Ah it is an ant ui component, I already removed it because I was just testing. Here is a simpler example:

(ns app.nav.views.authenticated
    ["antd" :refer [Layout]]))

(defn authenticated
    [:> Layout
     [:> Layout.Header


but I can't manage to use the Header component that is a subcomponent of Layout


Does (js/console.log Layout.Header) actually print anything?


When I try to log Layout.Header I get this error: Use of undeclared Var app.nav.views.authenticated/Layout


This is the current code I'm running:

(ns app.nav.views.authenticated
    ["antd" :refer [Layout]]))

(defn authenticated
  [:> Layout
   (js/console.log Layout.Header)
   [:h1 "OK"]]


I'm able to use the Layout component without any problems, but as soon as I try to log or use any of the subcomponents I get the error above. I'm using shadow-cljs.


Try (def Header (.-Header ^js Layout)).


It works! :star-struck: Thanks a lot

👍 3

What the ^js means? I never saw this before.


Perfect. Thank you very much!


It also works without the ^js


It may break with :advanced optimizations. Maybe imports are protected from this, but I've never seen mentions of it.


Ah, there it is: "No hint required for :as and :refer bindings"


So yeah, seems like you can omit ^js when working with imported stuff.


Cool! Good to know 🙏