1. Cheatsheet
  2. Google Closure Library
  3. Links
  4. Importing
  5. javascript to cljs
  6. cljs to javascript
    1. Accessing Javascript Properties
    2. Setting Property Values
  7. Namespaces
  8. String to Integer
  9. Random, Unique Symbol/Variable Name
  10. Binding
  11. Window and Document
  12. 3 Forms of Reagent Components


Google Closure Library

Closure Reference Api



There's a subtle difference between import and require. If you want to import a Closure Class, then use import. When you want to import javascript functions from a library, use require

 (ns async-tut1.core
   (:require [goog.events :refer [listen] :as ev])
   (:import  [goog.net XhrIo]))

javascript to cljs

(js->clj {:foo "bar"})

cljs to javascript

(clj->js {:foo "bar"})

Or, you can use the #js shorthand

#js {:foo "bar}

# Interop

Accessing Javascript Properties

.- operates on symbols. Advanced compile renames symbols. If you use only .- and set! then no problem (and you get nice compiler optimizations).

(.-prop obj) ;; obj.prop
(.. js/obj -prop1 -prop2) ;; obj.prop1.prop2

aget operates on names. Advanced compile ignores names. Lose some optimizations, but names are save to use from javascript

(aget js/obj "prop1" "prop2") ;; obj["prop1"]["prop2"]

Setting Property Values

set! corresponds to .-

(set! (.-prop1 obj) val) ;; obj.prop1 = val

Note that set! operates on symbols. Advanced compiler renames symbols.

aset corresponds to aget

(aset js/obj "prop1" "prop2" val) ;; obj["prop1"]["prop2"] = val

Note that aset operates on names. Advanced compiler leaves names intact.


Change namespaces from the clojurescript repl

(in-ns 'path.to.namespace)

Load cljs files from repl. load-namespace will also load dependencies

(load-namespace "path.to.namespace")

String to Integer

(js/parseInt "10")

Random, Unique Symbol/Variable Name

;; or

Binding this

Use this-as

Window and Document

js/window, js/document

3 Forms of Reagent Components

Form 1:

(defn greet
   [name]                    ;; data coming in is a string
   [:div "Hello " name])     ;; returns Hiccup (HTML)

Form 2:

(defn timer-component []
  (let [seconds-elapsed (reagent/atom 0)]     ;; setup, and local state
    (fn []        ;; inner, render function is returned
      (js/setTimeout #(swap! seconds-elapsed inc) 1000)
      [:div "Seconds Elapsed: " @seconds-elapsed])))

(defn outer 
  [a b c]            ;; <--- parameters
  ;;  ....
  (fn [a b c]        ;; <--- forgetting to repeat them, is a rookie mistake
      (str a b c)]))

Form 3:

(defn my-component
  [x y z]  
  (let [some (local but shared state)      ;; <-- closed over by lifecycle fns
        can  (go here)]   
     (reagent/create-class                 ;; <-- expects a map of functions 
       {:component-did-mount               ;; the name of a lifecycle function
        #(println "component-did-mount")   ;; your implementation

        :component-will-mount              ;; the name of a lifecycle function
        #(println "component-will-mount")  ;; your implementation

        ;; other lifecycle funcs can go in here

        :display-name  "my-component"  ;; for more helpful warnings & errors

        :reagent-render        ;; Note:  is not :render
         (fn [x y z]           ;; remember to repeat parameters
            [:div (str x " " y " " z)])})))