Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create Button Elements in ClojureScript?

I'm trying to create new elements in ClojureScript and it doesn't appear to be working. I'll start up by showing an example that I found here.

(let [dom6238 (.createElement js/document "a")]
    (.setAttribute dom6238 "href" "http://somelink")
    (set! (.-innerText dom6238) "Text")
    dom6238)

Which they say converts to:

var dom54535 = document.createElement("a");
    dom54535.setAttribute("href", "http://somelink.com");
    dom54535.innerText = "Hello there";
return dom54535

If I'm not mistaken, this should produce an HTML snippet that looks like:

[:a.anchor.silly {:href "http://somelink.com"} "Text"]

I have this in my .cljs file:

(defn create-button []
  (let [a (.createElement js/document "a")]
    (.setAttribute a "href" "http://somelink")
    (set! (.-innerText a) "Text")
    a))

(defn init []
  (let [a (.getElementById js/document "write-action")
        b (.getElementById js/document "button-field")]
    (set! (.-innerHTML a)
          "field a")
    (set! (.-innerHTML b)
          (create-button))))

Which just produces (button-field is above write-action in the HTML):

http://somelink/
field a

So there is no anchor tags, only text.


What I am attempting to do is create a button, so I have this code:

(defn create-button []
  (let [new-button (.createElement js/document "input")]
    (set! (.-type new-button)
          "button")
    (set! (.-innerHTML new-button)
          "I'm a button")
    new-button))

Which generates this output:

[object HTMLInputElement]
field a

So, I play around a bit and remove the return value:

(defn create-button []
  (let [new-button (.createElement js/document "input")]
    (set! (.-type new-button)
          "button")
    (set! (.-innerHTML new-button)
          "I'm a button")))

Which creates:

I'm a button
field a

Once again, I have only text.


And I have to be complete:

(defn create-button []
  (let [new-button (.createElement js/document "input")]
    (set! (.-type new-button)
          "button")))

Which only returns the text:

button
field a

And this:

(defn create-button []
  (let [new-button (.createElement js/document "input")]
    (set! (.-type new-button)
          "button")
    new-button))

Produces this:

[object HTMLInputElement]
field a

I'm completely lost here and I've searched high and low for any solution and there doesn't appear to be anything out there that answers this question. I've tried wrapping the new set attributes in (do) as well as as trying out versions without (set!) but nothing is creating the desired result.

Q: How do I create a button that can be clicked using ClojureScript?

Bonus Q if anyone knows: Why does the example from the site only return the result of the first item and not innerText while my examples only return the text results of the second (set!) functions?

like image 521
dizzystar Avatar asked Apr 20 '13 14:04

dizzystar


2 Answers

You are assigning a DOM element object to innerHTML property of another element which is obviously not going to work. You need to use appendChild method on the DOM element to insert a child element into it.

(let [div (.createElement js/document "DIV")]
    (.appendChild div (create-button)))
like image 72
Ankur Avatar answered Nov 13 '22 04:11

Ankur


Reagent provides a way to create html and js elements from CLJS without calling the JS namespace all the time. I found it much easier to understand. I know this is an old post but it pops up in many searches and this could help out people learning. Example:

(defn your-button []
[:div 
    [:input.btn {:type "button" :value "Click Me!"
        :on-click ( your func here ) }]])

CSS:

.btn {

}

Creates a button inside a div, more info here: https://github.com/reagent-project/reagent

like image 34
Jahsa Avatar answered Nov 13 '22 03:11

Jahsa