clojurescriptclojurescript-javascript-interop

ClojureScript change display none to visible


I want to modify the visibility of a table when a button is clicked, utilizing clojurescript/javascript interop.

I've tried

{:on-click #(-> js/document                                               
 (.getElementById "db-search-result-tables")                                               
 (.-style)
 (.-display "block"))}

This is the div tag I'm calling it on.

[:div {:style {
       :display "none"}
       :id "db-search-result-tables"
        :class "db-search-results-table"}
[table-to-display]

I've also tried

(-> js/document                                               
 (.getElementById "db-search-result-tables")                                                
 (.-style)
 (.-display)
  (set! ""))

but it only displays the table momentarily, and then sets display to none again.


Solution

  • EDIT: This solution doesn't assume any library, based on the reading that the problem statement didn't explicitly mention any library/framework, just JS interop, modifying the DOM directly a la jQuery. Don't use this answer if you use any library or any React wrapper such as reagent.


    Maybe it would be easier to create a helper function, say toggle that hides/shows the display of a given element by its ID?

    (ns myproject.core)
    
    (defn ^:export toggle [elem-id]
      (let [elem        (js/document.getElementById elem-id)
            style       (.-style elem)
            display     (.-display style)
            new-display (if (= "none" display) "block" "none")]
        (set! (.-display style) new-display)))
    

    We find the element by its id, use a var to get the current style, get the display out of the style and compute the new value for the display attribute, then we set! it back into the display.

    I used the ^:export metadata tag so that the function could be called directly from the document, like this:

        <div>
          <button onClick="myproject.core.toggle('details')">Toggle details</button>
        </div>
    
        <div id="details" style="display: none">
          Some details here. Some details here. Some details here. Some details here. 
        </div>