Hi all, I've recently released *Clidget v0.1.0*, a new lightweight CLJS state utility that allows you to build UIs through small, composable widgets.
Quick links: - GitHub <https://github.com/james-henderson/clidget> (README, Rationale and Getting Started) - Sample 'counter' application<https://github.com/james-henderson/clidget/tree/master/clidget-sample> - TodoMVC implementation<https://github.com/james-henderson/clidget/tree/master/todomvc> The fundamental idea behind Clidget is to ensure that you can write widgets declaratively, in traditional Clojure style, as a function that *takes in immutable values and returns a DOM element*. Then, rather than calling that function with values, you* call it with atoms*, and Clidget figures out when each widget needs to be re-rendered. So, a counter widget would look something like this (using Dommy to create the DOM element and core.async for event handling - you're free to choose whatever you like): (:require [cljs.core.async :as a] [dommy.core :as d] [clidget.widget :refer [defwidget] :include-macros true]) (:require-macros [dommy.macros :refer [node]] [cljs.core.async.macros :refer [go-loop]])) (defwidget counter-widget [{:keys [counter]} events-ch] (node [:div [:h2 "counter is now: " counter] [:p (doto (node [:button "Increment counter"]) (d/listen! :click #(a/put! events-ch :inc-counter)))]])) To include a widget in the page, call it (it’s just a function!), but provide it with the *atoms* that it needs to watch: (set! (.-onload js/window) (fn [] (let [!counter (atom 0) events-ch (doto (a/chan) ;; 'watch-events!' implemented below (watch-events! !counter))] (d/replace-contents! (.-body js/document) (counter-widget {:!counter !counter} events-ch)])))) (I'm prefixing the atom with '!', to easily differentiate between atoms and values) Finally, we implement watch-events! (no Clidget here): (defn watch-events! [events-ch !counter] (go-loop [] (when-let [event (a/<! events-ch)] (when (= :inc-counter event) (swap! !counter inc)) (recur)))) (We could do this inside the widget, given it's only a counter, but it's probably better to separate it!) *Why?!* The main design decision behind Clidget was to favour simplicity over performance (obviously within reason). Clidget does one thing (I hope it does it well!) - figuring out which widgets to re-render and when. How you update the state, render the widgets, pass the events, handle the events etc is completely up to you. There's no 'magic' in Clidget - you pass in atoms, it behaves pretty much like Clojure's add-watch function. I've found this to be a really useful quality when reasoning about applications - it makes the debugging headache a lot more manageable. Finally, I wanted to preserve Clojure's composability. One of the benefits I really enjoy about working with Clojure is the ability to use many small libraries without worrying about how they'll fit together. If you're a Hiccup person, you can use your favourite Hiccup-like library; if you're an Enlive/Mustache person, likewise! In Clidget, this also extends to JS libraries - when you're working with the DOM elements that will end up on the page, you can pass them to other JS libraries easily. I've received a number of requests for a comparison with Om/Cloact/React - it didn't fit into 140 characters, so it's here<https://github.com/james-henderson/clidget/blob/master/comparison.org> . *Feedback* The idea behind Clidget is still very much experimental - I'd be very interested to hear thoughts and feedback (good, bad, and 'what on earth were you thinking?!') on the approach and/or implementation, please let me know! GitHub, Twitter (@jarohen <https://twitter.com/jarohen>) or through here are all good. If you've got this far, thanks for reading! James -- -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.