I have code that updates the DOM.
new-recipe! calls an API to get a new recipe string.
update-recipe-state next updates this state in the screen. Finally we have a call to
(defn- add-listener-to-recipe-button!  "Listens to go button, creates a new recipe and displays it" (create-click-event-listener! (dommy/sel1 :#button-start) #(go (new-recipe!) (<! (timeout 2000)) (update-recipe-state!) (<! (timeout 2000)) (update-transition-buttons! "onboarding")))) ;; define your app data so that it doesn't get over-written on reload (defonce world (add-listener-to-recipe-button!))
update-transition-buttons has some delays between the steps (using the timeout code <a href="https://gist.github.com/swannodette/5882703" rel="nofollow">here</a>) looks as follows:
(defn- update-transition-buttons! [recipe-name] "Updates the buttons with the transition names" (go ;; Split response in list of actions by splitting on the comma (let [response (<! (http/get (get-recipe-transitions-url recipe-name))) transition-names (clojure.string/split (:body response) ",")] (go (update-buttons! transition-names) (<! (timeout 2000)) (js/console.log transition-names) (set-button-event-handlers! transition-names)))))
So it splits the response to a string.
updates-buttons changes state on the page by adding some buttons (this is visible). Again there is a timeout, and then I want to <em>add the event handlers to the buttons</em>. This is where it goes wrong.
The routine to create event listeners (which also contain a
console.log) look as follows:
(defn- listen-to-transition-button! [name] "Creates click event listener on button (button HTML ID should be name)" (do (js/console.log (str "Listening to " name)) (let [name-without-spaces (clojure.string/replace name " " "") button (dommy/sel1 (keyword (str "#" name-without-spaces))) action #(do (perform-action! name) (update-recipe-state!))] (create-click-event-listener! button action)))) (defn- set-button-event-handlers! [names] "Creates click event listeners on the buttons (button ID should be name)" (map listen-to-transition-button! names))
Again you see a
console.log message that should happen for each elements that is passed. The output I get in the Firefox console is:
[FIRST SERVICE CALLED]<br /> [NEXT SERVICE CALLED]<br /> [DISPLAY LIST OF STEPS]: ["Step1", "Step2", "Step3"]</blockquote>
What I expect is:<blockquote>
[FIRST SERVICE CALLED]<br /> [NEXT SERVICE CALLED]<br /> [DISPLAY LIST OF STEPS]: ["Step1", "Step2", "Step3"]<br /><strong>Listening to Step1<br /> Listening to Step2<br /> Listening to Step3</strong></blockquote>
So the event handlers (which depend on the HTML generated in the step before) are not added for some reason and the
console.log message is not displayed.
When I call the <em>same code</em> from the REPL I do see the output, i.e.:<blockquote>
repl=> (set-button-event-handlers! ["Step1","Step2", "Step3"])<br /> (#object[Object [object Object]] #object[Object [object Object]] #object[Object [object Object]])</blockquote>
And the console output is:<blockquote>
Listening to Step1<br /> Listening to Step2<br /> Listening to Step3</blockquote>
set-button-event-handlers! be called from the REPL, but not in the
update-transition-buttons method after
looks like the problem is here:
(map listen-to-transition-button! names)
it creates a lazy seq, and elements won't be realized until their usage somewhere in code (which never happens), but when you call it in repl, it is being fully realized to show all the elements in output. Try changing this line to:
(doall (map listen-to-transition-button! names))