Dirk Bergmann

Developer, panographer. Does consultancy work from own company. Lives in Chiang Mai, Thailand.

Twitter

Chiang Mai

Hua Hin

Thailand Hotels

ListVote - List. Vote. Learn.

Partnerseek - Find Partners

Star Rating Control with Clojurescript, Reagent, Facebook React JS

There are at least two Star Rating components for Facebook React that can be used with the brilliant Reagent.

I found these to be too complex and neigh impossible to integrate with Reagent so I came up with a simple solution like so:

(ns my-star-rating-control
  (:require [reagent.core :as reagent :refer [atom]])
  )
  
(defonce star-rating-info
  (atom {
         :rating-temp 0
         :rating 0
         :clicked false
         }))

(defn get-attr [x]
  (-> x .-target (.getAttribute "data-index") js/parseInt)
  )

(defn si-update [elem-kw upd]
  (swap! star-rating-info update-in [elem-kw] upd))

(defn set-active [index item-kw]
  (if (<= index (get-in @star-rating-info [item-kw]))
    " star_active"
    " star_inactive"))

(defn star-item [index]
  [:span {:class (str "rating_star" (if (get-in @star-rating-info [:clicked])
                                      (set-active index :rating)
                                      (set-active index :rating-temp)
                                        ))
          :data-index index
          :on-mouse-enter #(do
                             (si-update :rating-temp (fn [] (get-attr %)))
                             (si-update :clicked (fn [] false))
                             )
          :on-mouse-leave #(si-update :rating-temp (fn [] 0))
                                        ;:on-mouse-leave #(js/alert (-> % .-target (.getAttribute "data-index")))
          :on-click #(do
                       (si-update :rating (fn [] (get-attr %)))
                       (si-update :clicked (fn [] true)))

          } "\u2605"]
  )

(defn five-stars []
  [:div.star_container
   (for [x (range 1 6)]
   [star-item x])
   ])

It should be called like any other reagent component:

[five-stars]

Here's some styling:

.rating_star
{
    font-size: 32px;
    cursor: pointer;
}    

.star_active
{
 color: #F6B11C;
}

.star_inactive
{
    color: #D3D3D3;
}

The magic of Facebook React, Reagent and Clojure/Clojurescript is really coming together nicely here. Surely there are a few problems, e.g. that the user has to click the star pretty much exactly. But he gets proper feedback and it could be fixed with css.

Hope it helps.