Ajax form and Comet example
The "Ajax form" in closerve is in fact implemented with websocket, but we keep the lift:form.ajax tag to have better prtability of HTML code.
Here is an example of using form.ajax and comet to make a very simple chat app.
First, define some data structures for bookkeeping:
(def chat-chans (atom #{}))
(def chat-msgs (atom []))
Then we need a processing fuction for ajax.form which takes user input:
(register-cmd-proc-fn
"ChatInput"
[context cmd]
(let [chat-msg (cmd "chatmsg")]
(if (string? chat-msg)
(do
(swap! chat-msgs #(apply vector (drop (- (count %1) 9)
(conj %1 %2))) chat-msg)
(send-cmd-to-page (:page-id context)
{:act :reset
:selector
(str "#" (:form-id context))})
)
))
)
Distribute the input msg to all comet channels, kind of like the comet actor server in Lift:
(add-watch chat-msgs :watch-chat-msgs
(fn [key aref old-val new-val]
(if new-val
(doseq [c @chat-chans]
(go (>! c (last new-val)))))))
Now the comet actor which read input from its channel and send update to browser:
(register-comet-fn
"chat"
[ch req page-id uuid]
(swap! chat-chans conj ch)
(loop [msg (<! ch)]
(when msg
(send-cmd-to-page page-id
{:act :append
:selector "#msglist"
:html (hickory-to-html {:type :element, :attrs nil
:tag :li :content [msg]}) })
(recur (<! ch))))
(prn "chat channel is closed")
(swap! chat-chans disj ch)
)
The corresponding HTML code:
<ul class="lift:comet?type=chat" id="msglist"></ul>
<form class="input-group lift:form.ajax?callback=ChatInput">
<input name="chatmsg" type="text" class="form-control">
<span class="input-group-btn">
<input value="Go!" class="btn btn-default" type="submit">
</span>
</form>
Try it here: