5

I'm having trouble getting my table body to line up properly using clojurescript / reagent. I'm actually not sure if this is me not understanding what to do in html or what...

Currently I display the table body using a loop

(defn table-body [list-of-maps] 
[:tbody
  (for [one-map list-of-maps]
     [:tbody
      [:tr
       [:td (:key1 one-map)]
       [:td (:key2 one-map)]
       [:td (:key3 one-map)]
       [:td (:key4 one-map)]
       [:td (:key5 one-map)]
       [:td (:key6 one-map)]
       [:td (:key7 one-map)]]
      [:tr
       [:td (:key8 one-map)]]])])

The problem is that I need to group both outside the for and inside the for using some html element, right? If I use [:tbody] on both it will mess up the alignment with the [:thead] section. If I use an element other than tbody then it creates all kinds of other issues. Everything looks fine if I remove the [:tbody] in the for loop and the last [:tr].

Edit: I've currently narrowed down the problem a lot. My app ajax gets and derefs data involved with the table. On this re-render the formatting of the table gets messed up.

Edit2: I've found the issue.

(defn test-body [list-of-maps]
[:tbody
  (for [one-map @list-of-maps]
     [:tbody
      [:tr
       [:td (:key1 one-map)]
       [:td (:key2 one-map)]
       [:td (:key3 one-map)]
       [:td (:key4 one-map)]
       [:td (:key5 one-map)]
       [:td (:key6 one-map)]
       [:td (:key7 one-map)]]
      [:tr
       [:td (:key8 one-map)]]])])

(defn test-head []
  [:thead
   [:th "key1"]
   [:th "key2"]
   [:th "key3"]
   [:th "key4"]
   [:th "key5"]
   [:th "key6"]
   [:th "key7"]])

(defn test55 []
  (let [list-of-maps (reagent/atom [])]
    (js/setTimeout (fn [] (reset! list-of-maps '({:key1 "a1" :key2 "a2" :key3 "a3" :key4 "a4" :key5 "a5" :key6 "a6" :key7 "a7" :key8 "a8"} {:key1 "b1" :key2 "b2" :key3 "b3" :key4 "b4" :key5 "b5" :key6 "b6" :key7 "b7" :key8 "b8"}))) 3000)
    [:table
     [test-head]
     [test-body list-of-maps]]))

When the list-of-maps re-renders the alignment of the table breaks.

2 Answers2

1

It turns out this problem can be solved by thinking about things just simply as vectors. What vector do you want the end result to look like?

[:tbody 
   [:tr 
      [:td "a1"] [:td "a2"] [:td "a3"] [:td "a4"] [:td "a5"] [:td "a6"] [:td "a7"]] 
   [:tr 
      [:td "a8"]] 
   [:tr 
      [:td "b1"] [:td "b2"] [:td "b3"] [:td "b4"] [:td "b5"] [:td "b6"] [:td "b7"]] 
   [:tr 
      [:td "b8"]]]

So with this as our goal, we set out to have the body function create this.

(defn test-body [list-of-maps]
  (into [] (concat [:tbody] (apply concat (for [one-map @list-of-maps]
                                            [
                                             [:tr
                                              [:td (:key1 one-map)]
                                              [:td (:key2 one-map)]
                                              [:td (:key3 one-map)]
                                              [:td (:key4 one-map)]
                                              [:td (:key5 one-map)]
                                              [:td (:key6 one-map)]
                                              [:td (:key7 one-map)]]
                                             [:tr
                                              [:td (:key8 one-map)]]])))))

This is my solution. There may be a better one.

0

I guess your problem is unequal number of cells in the rows. HTML TD element has COLSPAN attribute. Try setting in the last row, to the number of cells in the above rows.

(defn test-body
  [list-of-maps]
  [:tbody
    (for [one-map @list-of-maps]
       [:tbody
        [:tr
         [:td (:key1 one-map)]
         [:td (:key2 one-map)]
         [:td (:key3 one-map)]
         [:td (:key4 one-map)]
         [:td (:key5 one-map)]
         [:td (:key6 one-map)]
         [:td (:key7 one-map)]]
        [:tr
         [:td {:colspan 7} (:key8 one-map)]]])])
skrat
  • 5,518
  • 3
  • 32
  • 48