8

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?

3
  • Could you please accept Ankur's answer if it works for you? Commented Apr 20, 2013 at 17:38
  • 1
    @deterb Sure, but is that really good form? I mean, it's like me asking you to upvote my question if it was helpful to you. The reason I didn't want to accept it right off is because I've seen answers simply hinted at but never elaborated on because another answer was already chosen. I prefer to wait a few days before choosing an answer because of this. If you look at my history, every topic I've posted has a chosen answer. Commented Apr 20, 2013 at 19:43
  • Interesting perspective, I like where you are coming from. I see enough cases where people comment on an answer and then don't select it that I put up a reminder comment as I come across them. I'll give the next pairing more time then. Commented Apr 22, 2013 at 3:07

2 Answers 2

8

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)))
Sign up to request clarification or add additional context in comments.

1 Comment

Ah, I see now. I was using (.appendChild) before but was messing up the syntax a bit by wrapping it in (set!). Turns out I can just append to the div that already exists. Perfect answer.
3

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.