This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-04-21
Channels
- # admin-announcements (2)
- # beginners (22)
- # boot (223)
- # cider (161)
- # cljs-dev (19)
- # cljsrn (4)
- # clojure (186)
- # clojure-austin (6)
- # clojure-beijing (1)
- # clojure-boston (3)
- # clojure-china (1)
- # clojure-czech (1)
- # clojure-france (1)
- # clojure-greece (10)
- # clojure-russia (17)
- # clojure-uk (154)
- # clojurebridge (3)
- # clojurescript (82)
- # component (12)
- # cursive (12)
- # datomic (71)
- # dirac (3)
- # editors (2)
- # emacs (29)
- # flambo (31)
- # hoplon (21)
- # immutant (11)
- # instaparse (17)
- # jobs (2)
- # jobs-discuss (2)
- # jobs-rus (1)
- # lein-figwheel (12)
- # leiningen (2)
- # off-topic (44)
- # om (78)
- # onyx (38)
- # parinfer (1)
- # re-frame (34)
- # reagent (32)
- # spacemacs (56)
- # untangled (74)
- # vim (12)
- # yada (2)
@iwankaramazow: nice work on this router. Just out of curiosity, how do you recommend handling remote fetches to server? I couldn't ever get it to work with a recursive parser...
@tmorten: I mostly do something like:
(defmethod read :app
[{:keys [parser query ast target] :as env} key _]
(let [remote (parser env query target)]
(if (and target (not-empty remote))
{:remote (update-in ast [:query] (fn [query] remote))}
{:value (parser env query)})))
And then I work with :query-root true
with on subqueries, don't forget to use process-roots
in your send function
Example when :app
contains some :navbar/items
(defmethod read :navbar/items
[{:keys [query state ast]} key params]
(let [st @state]
(if (nil? (get-in st [:app key]))
{:remote (assoc ast :query-root true) }
{:value (om/db->tree query (get-in st [:app key]) st)})))
(defn transit-post [url]
(fn [{:keys [remote] :as env} cb]
(let [{:keys [query rewrite]} (om/process-roots remote)]
(.send XhrIo url
(fn [e]
(this-as this
(cb (rewrite (t/read (t/reader :json) (.getResponseText this))))))
"POST" (t/write (t/writer :json) query)
#js {"Content-Type" "application/transit+json"}))))
@iwankaramazow: makes sense. Thank you for the help!
When I do mapping/looping on dom elements in om (using Sablono), in what cases can this warning hunt me back: Warning: Each child in an array or iterator should have a unique "key" prop.
Sorry - I’m bringing a question to the #C06DT2YSY channel from the #C03S1L9DN channel - basically I’ve been playing with implementing an existing react app to om.next. In the existing app, when a user logs in, I dispatch an ajax request for supplemental information associated with the user (which is then loaded in the app state).
I think the way to do something similar in om.next is to follow the suggestions in the “Remote Synchonization Tutorial” ie. create a read function for that data that conditionally triggers a remote synchronization. Am I on the right track?
@hlolli: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children
@mattyulrich: sounds like the right approach: write a read function for your extra user data, return it from state if it exists or read from a remote & merge it into your state if it doesn't
@devth: https://github.com/awkay/om-tutorial/blob/master/src/main/om_tutorial/simulated_server.cljs
I'm currently trying to use the most recent release of om (alpha 32) but getting an error "No such namespace: cljsjs.react.dom". I added a dependency for [cljsjs/react-dom "15.0.1-1"], but still no luck. Any ideas what I'm doing wrong here?
Ahh, nvm, it likely has to do with the fact that I'm trying to add om to a project that already uses reagent, which uses an old version of react + react-dom.
I'm using a javascript library which has a function which returns an HTMLImageElement. How can I include that object in an Om component?
@mattyulrich: yes you're on the right track, you could also go with a mutation, but a read makes more sense in this scenario (I think)
@cszentkiralyi: I guess I’m missing something with the reconciler behavior. Let me see if I can lay out a meaningful and concise example...
Let's say this is a class registration system where users register for classes - my reconciler defines: :remotes [:class-search] :send get-remote-classes
I've tested the send function; it collects the correct data if I pass in a user. But I can't seem to figure out what the reconciler injects to this function.
a map of remotes and a callback
My UI has elements that query for :classes and the reader looks like: '(defmethod read :classes [{:keys [state] :as env} key params] (let [user (read env :user params)] (merge {:value (get @state key [])} (when (and (not (find @state key)) (not (= :not-found (:value user)))) {:class-search ???}))))'
the callback is basically merge!
I can break in my sender - but can't seem to put the right info in the '???' bit to get the reconciler to provide me with app-state or user or anything meaningful.
Right - that “map of remotes” - that’s the bit...
Where does it build that?
when initializing the reconciler
the default one is :remote
but if you add others and return :other-remote
or whatever remote you added in your parser
send will receive them
hrm - so my problem is that I need to get the :user data from app-state in the send method. I thought it made sense to have the reconciler inject that; but it sounds like I’m misinterpreting the role of the reconciler here...
Indeed 😄
every parser method receives the app-state under :state
in the env
you've got full control over what you return in parser methods
so - when I return that map from my "read :classes” method {:value … :class-search ???}, I can see the reconciler invokes the send method…. but that’s not a parser method, right? so the :state isn’t available there, right?
@mattyulrich: you can also update the AST in the local parse function before it's sent to the send function:
(defmethod mutate 'user/update-option
[{:keys [state ast] :as env} _ params]
:value {:keys [:user]}
:action #( ... )
:remote (-> ast
(assoc-in [:params :uid] (get-in @state [:ui/auth :uid])))})
ahh… that makes sense
Thats a mutation by the way
(defmethod read :classes
[{:keys [state] :as env} key params]
(let [user (read env :user params)] ;;this is invalid syntax
;; should be (let [user (get @state user])
(merge
{:value (get @state key)} ;; removed extra []
(when (and (not (find @state key)) ;;find? -> (get @state key)
(not (= :not-found (:value user))))
{:class-search true})))) ;; return true or an ast
The reconciler has a parser which interprets queries, if those interpreted queries return either {:remote true}
or {:remote ast}
, it will forward those to the send function
In the om-next remote synchronization tutorial the reconciler has :remotes [:remote :search]
Is remote and search each a different remote?
It doesn't get used in the tutorial 😉
only :search
:remote
could be removed
@iwankaramazow: Thanks for this! Unfortunately, I’m still not sure where to make the connection between the local app-state available in the read function and the data injected to the send function. Is it missing because :user isn’t a remote?
if your read function returns a remote (either {:a-remote true}
or {:a-remote ast}
, the reconciler will forward it to the send function
(defmethod read :user
[{:keys [state]} key _]
(let [st @state]
(if (get st key)
{:value (get st key)}
{:remote true})))
this read function will check if the key :user
is in the app state
if so it will return that, no remotes
however if :user
isn't in the app state
{:remote true}
will be returned, the reconciler will forward it to the send function
and there you will receive something like [{:remote [:user]} cb]
where cb is merge!
{:remote [:user]}
=> :remote
is the name of your remote and [:user]
the query
ok… that makes sense and is what I see in the debugger.
Ok - just reviewed the tutorial again after your description; so is the :query data is available in the :send function of the tutorial because it is part of the component query that initializes the read function?
Sorry to keep pestering on this - in the tutorial the :send function extracts :query data:
(defn send-to-chan [c]
(fn [{:keys [search]} cb]
(when search
(let [{[search] :children} (om/query->ast search)
query (get-in search [:params :query])]
(put! c [query cb])))))
I’m suspecting that the om/query->ast call is populating that :query data...
If so - does it get that data because :query is part of the component query function or because it’s part of the component params function ?
The tutorial is a bit misleading, (om/query->ast search) is more of an 'advanced' scenario
:query
is here something that's part of the IQueryParams
a better name would be :search-text
or something
as you say, it comes from the params of the component
Ok - so I don’t need to call om/query->ast to populate the params?
Not at all
that functions takes a query and returns an ast
the abstract syntax tree is something you probably want to modify if you need to restructure queries or pull some parts out
So - if I put :user-id in the params of my component and come up with a way to om/set-query! on that component after the user logs in, I should be able to extract that in my send function?
only if your parser returns a remote with that component's query
As an exercise you should implement that
I'm going to make an example with authentication tomorrow for Om-Router
I'll send it
Ok - I will play with this! Thank you so much for the help; while I still feel in the dark, I think I feel a path to understand this stuff.