Ganelon is fully Ring compatible and based on Compojure and lib-noir. Being a AJAX focused, it is not a direct replacement for Noir. It can rather ease the pain of handling dynamic page requests in any Ring-based web application.
The execution model is heavily influenced by Weblocks or Vaadin, but without session-statefulness and out-of-the-box rich user interface:
- Certain parts of the page can be scoped as Widgets (for example using id attribute in HTML or ganelon.web.widgets.with-div utility macro) and referenced by id in Actions, and updated by Operations. Widgets can reference Actions to be invoked.
- Actions are invoked as XHR requests and return a set of Operations to be performed client-side. Actions are in fact simple Ring handlers.
- Operations provide abstraction layer over client-side JavaScript execution - e.g. using Bootstrap Modal or just updating part of DOM tree (a Widget or any other) or open certain URL in a browser window - or just anything else that has a simple integration layer provided.
The source codes are on GitHub: http://github.com/tlipski/
Sample code (a shoutbox) is listed below:
;A Widget, returning HTML code:
(defn box-widget []
(widgets/with-div
[:p "Call count (since restart): " [:b @COUNTER] ". Last 4 entries:"]
(for [entry @ENTRIES]
[:div.hibox [:b (:time entry)] ": "
(hiccup.util/escape-html (:msg entry))])
(widgets/action-form "say-hi" {} {:class "form-inline"}
[:input {:name "msg" :placeholder "Say hi!" :type "text"
:maxlength "20" :size "20"}] " "
[:button {:class "btn btn-primary"} "Send!"])))
;An Action, performing side effects and returning part of the page to be updated
(actions/defwidgetaction "say-hi" [msg]
(swap! COUNTER inc)
(swap! ENTRIES #(util/smart-subvec (flatten [(mkmsg msg) %]) 0 4))
(box-widget))
JavaScript code uses jQuery and optionally Bootstrap, but the implementation is really trivial and therefore easy to replace using your favorite JS library.
No comments:
Post a Comment