I'm toggling on/off series in chart and was wondering if I was doing anything crazy.

Is the atom really a good idea here?

;; ================ Graph data ================

(def serie1 {:label "Bar" :data [[11 13] [19 11] [30 -7]]})
(def serie2 {:label "Foo" :data [[10 1] [17 -14] [30 5]]})
(def serie3 {:label "Zon" :data [[8 2] [18 7] [30 15]]})

(def series (for [serie [serie1 serie2 serie3]]
              {:label (:label serie) :action "toggle-serie" :param serie}))

;; ============ Chart state ================

(def !chart
  "Chart state"
  (atom []))

(defn toggle-serie! [serie]
  "Return the series collection minus/plus the given serie"
  (swap! !chart #(if (some #{serie} %)
                   (remove #{serie} %)
                   (conj % serie))))

(defn reset-chart []
  "Reset chart state"
  (reset! !chart []))

;;================ Page population ================

; almost identical to ibdknox overtone example
(defpartial button [{:keys [label action param]}]
  [:a.button {:href "#" :data-action action :data-param param} label])

(defn populate [container buttons]
  (doseq [b buttons]
    (append container (button b))))

(populate ($ :#series) series)

;; ================ Button functions ================

(defn plot
  "Plot the given series and return the chart as an object."
  [placeholder coll-data & options]
  (js/jQuery.plot placeholder (clj->js coll-data) (clj->js options)))

(def chart ($ :#chart))

(defn toggle-serie-and-update-chart!
  "Add or remove a serie form the chart atom and redraw the chart."
  (toggle-serie! serie) ;update the chart atom
  (plot chart @!chart)) ; redraw the chart

(delegate ($ :#series) button :click
          (fn [e]
            (.preventDefault e)
            (this-as me 
                     (let [$me ($ me)
                           param (cljs.reader/read-string (data $me :param))]
                       (toggle-serie-and-update-chart! param)))))

If your dataset were coming from an outside source, like an API call, I'd say the atom would make sense. In this case, your dataset is static. In that case, I think I might find it more intuitive to use a var for the series and then select the items out that you want to plot. In that case, your state is really just a list of which series (you are selecting).

So, if you had all your series:

(def all-series
  {:series1 :...series1
   :series2 :...series2
   :series3 :...series3})

!chart might contain #{:series1 :series3} and you could get all the values out using (select-keys all-series @!chart).

You might find you can avoid the atom altogether, but at the very least I'd always look for ways to keep that state as simple as


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.