Last active
August 29, 2015 14:04
-
-
Save celldee/7306ba8add96f0dcebfe to your computer and use it in GitHub Desktop.
om-async intermediate tutorial - add class functionality not working
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
core.cljs | |
--------- | |
(ns om-async.core | |
(:require-macros [cljs.core.async.macros :refer [go]]) | |
(:require [cljs.core.async :as async :refer [put! chan alts!]] | |
[goog.dom :as gdom] | |
[om.core :as om :include-macros true] | |
[om.dom :as dom :include-macros true] | |
[om-sync.core :refer [om-sync]] | |
[om-sync.util :refer [tx-tag edn-xhr]])) | |
(enable-console-print!) | |
(def ^:private meths | |
{:get "GET" | |
:put "PUT" | |
:post "POST" | |
:delete "DELETE"}) | |
(def app-state | |
(atom {:classes []})) | |
(defn display [show] | |
(if show | |
#js {} | |
#js {:display "none"})) | |
(defn handle-change [e data edit-key owner] | |
(om/transact! data edit-key (fn [_] (.. e -target -value)))) | |
(defn end-edit [data edit-key text owner cb] | |
(om/set-state! owner :editing false) | |
(om/transact! data edit-key (fn [_] text) :update) | |
(when cb | |
(cb text))) | |
(defn editable [data owner {:keys [edit-key] :as opts}] | |
(reify | |
om/IInitState | |
(init-state [_] | |
{:editing false}) | |
om/IRenderState | |
(render-state [_ {:keys [editing on-edit]}] | |
(let [text (get data edit-key)] | |
(dom/tr nil | |
(dom/td nil | |
(dom/span #js {:style (display (not editing))} text) | |
(dom/input | |
#js {:style (display editing) | |
:value text | |
:size "60" | |
:onChange #(handle-change % data edit-key owner) | |
:onKeyPress #(when (== (.-keyCode %) 13) | |
(end-edit data edit-key text owner on-edit)) | |
:onBlur (fn [e] | |
(when (om/get-state owner :editing) | |
(end-edit data edit-key text owner on-edit)))})) | |
(dom/td nil | |
(dom/button | |
#js {:className "btn btn-primary" | |
:style (display (not editing)) | |
:onClick #(om/set-state! owner :editing true)} | |
"Edit"))))))) | |
(defn create-class [classes owner] | |
(let [class-id-el (om/get-node owner "class-id") | |
class-id (.-value class-id-el) | |
class-name-el (om/get-node owner "class-name") | |
class-name (.-value class-name-el) | |
new-class {:class/id class-id :class/title class-name}] | |
(om/transact! classes [] #(conj % new-class) [:create new-class]) | |
(set! (.-value class-id-el) "") | |
(set! (.-value class-name-el) ""))) | |
(defn classes-view [classes owner] | |
(reify | |
om/IRender | |
(render [_] | |
(dom/div #js {:id "classes"} | |
(dom/div #js {:className "panel panel-default"} | |
(dom/div #js {:className "panel-heading"} | |
(dom/h3 #js {:className "panel-title"} "Classes")) | |
(dom/div #js {:className "table-responsive"} | |
(dom/table #js {:className "table table-hover"} | |
(dom/thead nil | |
(dom/tr #js {:className "active"} | |
(dom/th nil "Title") | |
(dom/th nil))) | |
(apply dom/tbody nil | |
(map | |
(fn [class] | |
(let [id (:class/id class)] | |
(om/build editable class | |
{:opts {:edit-key :class/title}}))) | |
classes)))) | |
(dom/div #js {:className "panel-footer"} | |
(dom/label nil "ID:") | |
(dom/span nil "\u00A0") | |
(dom/input #js {:ref "class-id"}) | |
(dom/span nil "\u00A0") | |
(dom/label nil "Name:") | |
(dom/span nil "\u00A0") | |
(dom/input #js {:ref "class-name"}) | |
(dom/span nil "\u00A0") | |
(dom/button | |
#js {:className "btn btn-primary" | |
:onClick (fn [e] (create-class classes owner))} | |
"Add"))))))) | |
(defn app-view [app owner] | |
(reify | |
om/IWillUpdate | |
(will-update [_ next-props next-state] | |
(when (:err-msg next-state) | |
(js/setTimeout #(om/set-state! owner :err-msg nil) 5000))) | |
om/IRenderState | |
(render-state [_ {:keys [err-msg]}] | |
(dom/div nil | |
(om/build om-sync (:classes app) | |
{:opts {:view classes-view | |
:filter (comp #{:create :update :delete} tx-tag) | |
:id-key :class/id | |
:on-success (fn [res tx-data] (println res)) | |
:on-error | |
(fn [err tx-data] | |
(reset! app-state (:old-state tx-data)) | |
(om/set-state! owner :err-msg | |
"Ooops! Sorry something went wrong try again later."))}}) | |
(when err-msg | |
(dom/div nil err-msg)))))) | |
(let [tx-chan (chan) | |
tx-pub-chan (async/pub tx-chan (fn [_] :txs))] | |
(edn-xhr | |
{:method :get | |
:url "/init" | |
:on-complete | |
(fn [res] | |
(reset! app-state res) | |
(om/root app-view app-state | |
{:target (gdom/getElement "classes") | |
:shared {:tx-chan tx-pub-chan} | |
:tx-listen | |
(fn [tx-data root-cursor] | |
(put! tx-chan [tx-data root-cursor]))}))})) | |
(om/root classes-view app-state | |
{:target (gdom/getElement "classes")}) | |
core.clj | |
-------- | |
(ns om-async.core | |
(:require [ring.util.response :refer [file-response]] | |
[ring.adapter.jetty :refer [run-jetty]] | |
[ring.middleware.edn :refer [wrap-edn-params]] | |
[compojure.core :refer [defroutes GET PUT POST]] | |
[compojure.route :as route] | |
[compojure.handler :as handler] | |
[datomic.api :as d])) | |
(def uri "datomic:free://localhost:4334/om_async") | |
(def conn (d/connect uri)) | |
(defn index [] | |
(file-response "public/html/index.html" {:root "resources"})) | |
(defn generate-response [data & [status]] | |
{:status (or status 200) | |
:headers {"Content-Type" "application/edn"} | |
:body (pr-str data)}) | |
(defn get-classes [db] | |
(->> (d/q '[:find ?class | |
:where | |
[?class :class/id]] | |
db) | |
(map #(d/touch (d/entity db (first %)))) | |
vec)) | |
(defn init [] | |
(generate-response | |
{:classes {:url "/classes" :coll (get-classes (d/db conn))}})) | |
(defn create-class [params] | |
(let [id (:class/id params) | |
db (d/db conn) | |
title (:class/title params)] | |
(d/transact conn [{:db/id (d/tempid :db.part/user) | |
:class/title title | |
:class/id id}]) | |
(generate-response {:status :ok}))) | |
(defn update-class [params] | |
(let [id (:class/id params) | |
db (d/db conn) | |
title (:class/title params) | |
eid (ffirst | |
(d/q '[:find ?class | |
:in $ ?id | |
:where | |
[?class :class/id ?id]] | |
db id))] | |
(d/transact conn [[:db/add eid :class/title title]]) | |
(generate-response {:status :ok}))) | |
(defn classes [] | |
(generate-response (get-classes (d/db conn)))) | |
(defroutes routes | |
(GET "/" [] (index)) | |
(GET "/init" [] (init)) | |
(GET "/classes" [] (classes)) | |
(POST "/classes" {params :edn-params} (create-class params)) | |
(PUT "/classes" {params :edn-params} (update-class params)) | |
(route/files "/" {:root "resources/public"})) | |
(def app | |
(-> routes | |
wrap-edn-params)) | |
(defonce server | |
(run-jetty #'app {:port 8080 :join? false})) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment