day8 / re-com

A ClojureScript library of reusable components for Reagent

Home Page:https://re-com.day8.com.au

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow v-table :model to render re-frame subscriptions as well as reagent atoms?

ryrobes opened this issue · comments

Hi - I am unable to get v-table / simple-v-table to accept anything other than a "hard" reagent atom. Passing my re-frame subscription gets interpreted as a regular vector of maps, and putting my subscription result into an atom (while passing validation) renders as an empty vector would. Is there a workaround - maybe I am missing something?

Anyways - love the library! Cheers.

Thanks for the report @ryrobes 😄

By a

"hard" reagent atom

are you referring to reagent.ratom/atom and by

putting my subscription result into an atom

are you referring to a cljs.core/atom ?

If that is the case then I can confirm only the reagent.ratom/atom (usually abbreviated as r/atom) will work for :model for v-table or any other re-com component.

This is because reagent views need to keep track of derefs. There is some information available in the reagent documentation.

We successfully use re-frame subscriptions and r/atoms daily with v-table in our commercial applications so I don't think there is a bug with the code.

However I think there are at least two issues we do need to fix:

  1. Documentation bug. The current v-table documentation at https://re-com.day8.com.au/#/v-table only mentions atom containing vec of maps and nothing about r/atom which is certainly confusing and I imagine what misled you ? Other components such as checkbox mention r/atom although that is still quite subtle. Is r/atom enough to point library users in the right direction ?

  2. Validation bug. As you've rightly pointed out if r/atom is what is required and cljs.core/atom cannot work as expected then cljs.core/atom should fail validation, and it currently passes validation.

Those two issues together are a pretty brutal combination. We'd never have noticed this ourselves since it is more of a documentation issue so thank you for raising this issue otherwise I imagine quite a few users would continue struggling with this!

Appreciate the thoughtful response - yes, I meant an actual reagent atom (I think that your examples make that pretty clear actually), i.e. Forgive my lack of experience here - but generally in re-frame I will either deref the subscription in a let (probably a terrible practice), or do it inline, but am unable to get either of these methods to render.

i.e. (let [my-data @(rf/subscribe [::subs/my-data-fetching-sub]) and then :model my-data (which fails validation since it looks like a regular vector of maps), or even :model @(rf/subscribe [::subs/my-data-fetching-sub]) to be pedantic - or passing validation with something like :model (r/atom my-data) which passes, but doesn't properly render (and would possibly be hacky even if it did). In the rest of my code this generally works fine. I'm possibly missing something basic here, so apologies. :)

What is the pattern you use in this case? Again, appreciate it.

Update: I realize that I didn't make my request very succinctly before - can you please provide a small snippet or example of using a re-frame subscription to drive the :model (like you said happens in your other commercial projects)?

We do stuff like:

(defn foo-table
   (let [a @(rf/subscribe [::a])
          b (map-indexed ... a)]
     [rc/simple-v-table
        :model (-> b vec r/atom)]))

Thanks. I now realize now that my problem was an incorrect columns definition and not the sub data itself (i.e. it existed, passed validation, but was wrong). [Forehead Smack]

:model (reagent/atom my-sub-data) ; already a vector of uniform maps 

Works fine.

Maybe make that key optional and if it doesn't exist generate a simple one, a la

:columns (into [] 
           (for [k (keys (get my-sub-data 0))] 
              {:id k :header-label (str k) :row-label-fn k :width 150 :height 70}))

Regardless, closing this. Cheers.