Last active
February 26, 2017 18:43
-
-
Save smitch88/b6b0c19620c3e8d7e770 to your computer and use it in GitHub Desktop.
Generic Table Component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Removing the table component relying on a data fn | |
(def ext-data | |
[{:a "1" :b "2" :c "3" :d "4"} | |
{:a "5" :b "6" :c "7" :d "8"} | |
{:a "9" :b "10" :c "11" :d "12"}]) | |
(def table-options | |
{:id "some-table-id" | |
:fixed-headers true | |
:filterable false | |
:sortable true | |
:pagination true | |
:checkable true | |
:caption false | |
:footer false | |
:row-handlers {} | |
:column-defs [{:field :a | |
;; indicates header or this can be in a header-defs if we are so inclined | |
:display-name "Field A" | |
:cell-transform (fn [v] | |
[:div.custom-cell-markup | |
[:strong v]]) | |
:style {:min-width 100 | |
:background-color "#eee" | |
:font-weight 500}} | |
{:field :b | |
:display-name "Field B"} | |
{:field :c | |
:display-name "Field C"} | |
{:field :d | |
:display-name "Field D"}]}) | |
;; table render fn in some widget | |
(defn render-fn | |
[] | |
(let [table-comp (Table table-opts)] | |
(fn [] | |
(let [data ext-data] | |
[:div.table-container | |
[table-comp data]])))) | |
;; table component internals | |
;; default table styles | |
(defonce table-styles | |
{:head {:container {} | |
:row {} | |
:cell {}} | |
:body {:container {} | |
:row {} | |
:cell {}} | |
:footer {:container {} | |
:row {} | |
:cell {}}}) | |
;; data driven fns | |
(defn filter-data) | |
(defn sort-data) | |
(defn paginate-data) | |
;; markup fns | |
(defn make-filterable | |
[v] | |
[:div.filterable | |
v | |
;; add filter stuff below the value | |
[:div.filter-container | |
[:input {:type "text"}]]]) | |
(defn make-sortable | |
[v] | |
[:div.sortable-link | |
;; add sort stuff | |
[:a {:on-click do-sort!} v]]) | |
(defn wrap-header-cell | |
[v sortable filterable] | |
(if-not (or sortable filterable) | |
v | |
(do | |
(let [v (if sortable | |
(make-sortable v)] | |
(when filterable | |
[make-filterable v])))))) | |
(defn table-header | |
[{:keys [column-defs fixed-headers sortable filterable checkable] :as props}] | |
(let [headers-values (map-indexed :display-name column-defs)] | |
[:div.table-header-container {:class (if fixed-headers | |
"fixed-header" "non-fixed-header") | |
:style (get-in table-styles [:header :container])} | |
[:div.table-header-row {:style (get-in table-styles [:header :row])} | |
(for [[value idx] headers-values | |
;; this is what could potentially allow for dynamic widths | |
:let [cell-style (merge (get-in table-styles [:header :cell]) | |
(get-in column-defs [idx :style]))] | |
wrapped-value (wrap-header-cell sortable filterable value)] | |
[:div.table-header-cell {:style cell-style} | |
wrapped-value])]])) | |
(defn table-footer) | |
(defn table-body) | |
(defn table-row) | |
(defn table-cell) | |
(defn generate-table-state | |
"Dynamically creates an initial local state based on the props provided" | |
[{:keys [column-defs sort-init sortable filterable checkable pagination] :as props}] | |
(reagent/atom (cond-> {} | |
sortable (assoc :sort-obj {:dir "asc" | |
:field (or sort-init (:field (first column-defs)))}) | |
filterable (assoc :filter-obj {:value nil}) | |
checkable (assoc :checkable-obj {:toggle-all false | |
:toggled #{}}) | |
pagination (assoc :pagination-obj {:current-page 1})))) | |
(defn Table | |
[table-opts] | |
;; note that the sort/filter/page | |
(let [table-state (generate-table-state table-opts)] | |
(fn [data] | |
;; code up dynamic nature based on table-opts and the data passed in from the caller | |
(let [{:keys [sort-obj filter-obj checkable-obj pagination-obj]} @table-state | |
data (if sort-obj | |
(sort-by (:field sort-obj) (case (:dir sort-obj) | |
"asc" > | |
"desc" <)) | |
data) | |
data (if filter-obj | |
(filter (fn [v] | |
;;do filter stuff | |
) data) | |
data)] | |
[:div.table {:id (:id table-opts)} | |
[table-header table-opts] | |
[table-body | |
(for [row data] | |
;; table row is just a wrapping div that ends up displaying the cells | |
^{:key row} | |
[table-row | |
(for [cell row] | |
^{:key cell} | |
[table-cell cell])]] | |
(when (:pagination table-opts) | |
[table-pagination pagination-obj data]) | |
(when (:footer table-opts) | |
[table-footer data])])))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment