Fork me on GitHub
#re-frame
<
2020-07-31
>
Jason00:07:36

Hello. Front end newb trying to get a material ui table to pop up buttons on hover per table row, like gmail. i can get them to render, but i'm not sure how to wire up the events and states. i'm still missing some DOM stuff like how to use getElementById in cljs or maybe I'm making a more basic error. I've tried to simplify the code so apologies if any edit errors slipped through 1. Am I setting :anchorEl correctly? I get a warning about it being null, but the Popover shows up in the right place so it seems to be anchored and tarnsformed correctly. 2. In :on-mouse-enter, i would like to swap the current element's :id into local -state. I'm not sure of the syntax there and it's pretty google-proof. 3. I have to be making a mistake in how I calculate each Popover's :open property. Any help appreciated.

(defn location-table [{:keys [^js classes]}]
  (let [local-state (reagent/atom {:hover ""})
        locs (rf/subscribe [:the-app/locations])]
    (fn []
      [:> mui/Table {:size "small"}
       [:> mui/TableHead
        [:> mui/TableRow {:class (.-hoverable classes)}
         [:> mui/TableCell "Name"]
         [:> mui/TableCell "URL"] ]]
       [:> mui/TableBody
        (for [{:keys [id name url]} @locs]
          (let [this-id (str "row-" id)]
            ^{:key this-id}
            [:> mui/TableRow {:hover true
                              :id this-id
                              :class this-id
                              :key this-id
                              :on-mouse-enter #(swap! local-state
                                                      assoc :hover
                                                      (-> % .-target ???))
                              :on-mouse-leave #(swap! local-state
                                                      assoc :hover "")
                              }
             [:> mui/TableCell [:> Link name]]
             [:> mui/TableCell [:> Link url]] ]))]
       (for [{:keys [id]} @locs]
         (let [this-id (str "popver-" id)
               row-id (str "row-" id)]
           ^{:key this-id}
           [:> mui/Popover {:id this-id
                            :key this-id
                            :className (.-popover classes )
                            :open #(= row-id
                                      (:hover @local-state))
                            :anchorEl #(.getElementById js/document
                                                        (str "row-" id))
                            :anchorOrigin {:vertical "top"
                                           :horizontal "right"}
                            :transformOrigin {:vertical "top"
                                              :horizontal "right"}
                            :disableRestoreFocus true}
            [:> mui/Grid {:container true}
             [:> Tooltip {:title "Edit"}
              [:> IconButton {:aria-label "delete"
                              :class (.-avatar classes)}
               [:> icons/Edit]]]
             [:> Tooltip {:title "Delete"}
              [::> IconButton {:class (.-avatar classes)}
               [:> icons/Delete]]]
             ]]))])))

uosl11:08:34

According to the API docs (https://material-ui.com/api/popover/), :open should be a bool while you're passing a function. Just remove the # and you should be fine. For :on-mouse-enter, I think (-> % .-target .-id) should work. Although you might want to consider using React refs instead of IDs, see https://day8.github.io/re-frame/FAQs/FocusOnElement/#html-autofocus and https://github.com/reagent-project/reagent/blob/master/doc/FAQ/UsingRefs.md

David Pham05:07:01

Do you have some examples of locs?

Jason14:07:20

@neo2551 I do. Something like this:

{:id (uuid)
:name "string"
:url ""}
I simplified the code I posted because the hover event wiring is the issue and more columns would just make the sample longer.