Sortable Table
Subscribe to a paid plan to get instant access to this lesson.
Download  Video time: 34m16s

Sortable Table

We build a reusable sortable table component using Re-frame and ClojureScript.

Code is available: lispcast/building-re-frame-components

You can checkout the code in your local repo with this command:

$CMD git clone git@github.com:lispcast/building-re-frame-components.git
$CMD cd building-re-frame-components          

Loading compiler
            
              (ns student.sortable-table
  (:require [reagent.core :as reagent]
            [re-frame.core :as rf]))

(def data
  [["Name" "Weapon" "Side" "Height (m)"]
   ["Luke Skywalker" "Blaster" "Good" 1.72]
   ["Leia Organa" "Blaster" "Good" 1.5]
   ["Han Solo" "Blaster" "Good" 1.8]
   ["Obi-Wan Kenobi" "Light Saber" "Good" 1.82]
   ["Chewbacca" "Bowcaster" "Good" 2.28]
   ["Darth Vader" "Light Saber" "Bad" 2.03]
   ])

(rf/reg-event-db
 :initialize
 (fn [db _]
   {}))

(defn ui []
  [:div
   "Put table here"])

(defonce _init (rf/dispatch-sync [:initialize]))
(reagent/render [ui] (js/document.getElementById "student-container"))            
          
Loading compiler
              
                (ns teacher.sortable-table
  (:require [reagent.core :as reagent]
            [re-frame.core :as rf]))

(def data
  [["Name" "Weapon" "Side" "Height (m)"]
   ["Luke Skywalker" "Blaster" "Good" 1.72]
   ["Leia Organa" "Blaster" "Good" 1.5]
   ["Han Solo" "Blaster" "Good" 1.8]
   ["Obi-Wan Kenobi" "Light Saber" "Good" 1.82]
   ["Chewbacca" "Bowcaster" "Good" 2.28]
   ["Darth Vader" "Light Saber" "Bad" 2.03]
   ])

(rf/reg-event-db
 :teacher/initialize
 (fn [db _]
   (assoc db :teacher/tables {:new-hope {:header (first data)
                                         :rows (rest data)}})))

(rf/reg-sub
 :teacher/table
 (fn [db [_ key]]
   (get-in db [:teacher/tables key])))

(defn sortable-table [table-key]
  (let [s (reagent/atom {})]
    (fn [table-key]
      (let [table @(rf/subscribe [:teacher/table table-key])
            key (:sort-key @s)
            dir (:sort-direction @s)
            rows (cond->> (:rows table)
                   key (sort-by #(nth % key))
                   (= :ascending dir) reverse)
            sorts [key dir]]
        [:table {:style {:font-size "80%"}}
         [:tr
          (for [[i h] (map vector (range) (:header table))]
            [:th
             {:on-click #(cond
                           (= [i :ascending] sorts)
                           (swap! s dissoc
                                  :sort-direction :sort-key)
                           (= [i :descending] sorts)
                           (swap! s assoc
                                  :sort-direction :ascending)
                           :else
                           (swap! s assoc
                                  :sort-key i
                                  :sort-direction :descending))}
             [:div {:style {:display :inline-block}}
              h]
             [:div {:style {:display :inline-block
                            :line-height :1em
                            :font-size :60%}}
              [:div
               {:style {:color (if (= [i :descending] sorts)
                                 :black
                                 "#aaa")}}
               "▲"]
              [:div
               {:style {:color (if (= [i :ascending] sorts)
                                 :black
                                 "#aaa")}}
               "▼"]]])]
         (for [row rows]
           [:tr
            (for [v row]
              [:td v])])]))))

(defn ui []
  [:div
   [sortable-table :new-hope]])

(defonce _init (rf/dispatch-sync [:teacher/initialize]))
(reagent/render [ui] (js/document.getElementById "teacher-container"))              
            

Building Re-frame Components

Collapsible Panel free 25 min
Sortable Table 34 min
Inline Editable Field 29 min
Progress Bar 30 min
Password Box 26 min
Sortable Table in the Database 25 min
Tag Editor 26 min
Markdown Editor with Live Preview 9 min
Externally Managed Components 12 min
Accordion Component 27 min
Draggable List 36 min
Expanding Table 13 min
Filterable List 22 min
Username Box 1 hr
Username and Password Refactoring 22 min
User-Password Further Refactoring 17 min
User Registration 1 16 min
User Registration 2 28 min
User Registration 3 25 min