kishanov / re-frame-datatable

DataTable component for re-frame library
https://kishanov.github.io/re-frame-datatable/
Eclipse Public License 1.0
103 stars 16 forks source link

Allow changes to columns/options #4

Open smee opened 7 years ago

smee commented 7 years ago

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

kishanov commented 7 years ago

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

raduvarga commented 7 years ago

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".

jcthalys commented 7 years ago

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

kishanov commented 7 years ago

@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)