re-frame-datatable
re-frame-datatable copied to clipboard
Allow changes to columns/options
Currently the component assumes that the columns and options are static and do not change after the initial render. This forbids features like allowing the user to change the number of items per page, add/remove columns etc.
An ugly hack can be found in my fork, but I think there should be a nicer approach, just not sure how...
There is another hack that let you achieve that without modifying internals of datatable
(defn variable-columns-datatable []
; Assuming that :enabled-columns subscription returns a set of column keys that should be shown,
; i.e. #{[:name] [:role]}
(let [enabled-columns (re-frame/subscribe [:enabled-columns])]
(fn []
^{:key (hash @enabled-columns)}
[dt/datatable
:datatable-key
[:data-sub]
(->> [{::dt/column-key [:name]
::dt/column-label "Name"}
{::dt/column-key [:role]
::dt/column-label "Role"}
{::dt/column-key [:date]
::dt/column-label "Date"}]
(filter #(@enabled-columns (::dt/column-key %))))])))
In this case if component's key is determined by what defines datatable, Reagent will automatcially remount it.
To make columns dynamic, you can create a small form (let say, list of checkboxes which determine which columns should be shown) and changes in this form will update the data-source for :enabled-columns subscription. This will automatically re-mount DataTable.
The only big issue that I see with this approach that it will delete DataTable's state (like sorted-by column) so probably the right solution for the future version would be to expose handlers that modify columns-def
My hack is to remount the datatable by explicitly calling ::mount with my desired new options (in my case pagination-per-page).
(defn re-mount-datatable [dt-id pagination-per-page]
(rf/dispatch [::dt/mount dt-id
datatable-columns-def
(datatable-options pagination-per-page)]))
But it would be nice that the "datatable" function would subscribe to "columns-def" and "options", not only to the "data".
I don't know if it comes from the same issue but, How would you add and remove column dynamically. I tried something like that:
[datatable
:column-key-id [:model.equipment/id]
:data-sub [::subs/find-all]
:columns-def [
(if [:model.equipment/implement?]
{::dt/column-key [:model.equipment/width]
::dt/column-label "LARGURA"
::dt/sorting {::dt/enabled? true}})
But the column still is renderized
@jcthalys if you change the structure of :columns-def you need to remount datatable, cause these options are only read by datatable when it's being initialized.
Quick and dirty solution is to have use an explicit key for your datatable which depends on the conditions inside columns-def, in this example you can use something like ^{:key @(re-frame/subscribe [:model.equipment/implement?])} before datatable component (assuming that it's a subscription)