This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-02-29
Channels
- # admin-announcements (6)
- # announcements (1)
- # beginners (1)
- # boot (104)
- # braid-chat (5)
- # cbus (1)
- # cider (2)
- # clojure (147)
- # clojure-japan (1)
- # clojure-poland (1)
- # clojure-russia (31)
- # clojurescript (16)
- # core-async (4)
- # css (2)
- # cursive (14)
- # datomic (40)
- # devcards (5)
- # dirac (100)
- # emacs (5)
- # funcool (1)
- # immutant (52)
- # juxt (4)
- # ldnclj (128)
- # lein-figwheel (12)
- # leiningen (26)
- # luminus (3)
- # mount (22)
- # off-topic (11)
- # om (144)
- # onyx (2)
- # parinfer (1)
- # proton (7)
- # re-frame (55)
- # reagent (16)
- # slack-help (5)
- # yada (1)
@tony.kay: ooh yeah, I've had to do that. how is your data normalized then? I didn't think you were doing that part differently
@jlongster: data is normalized as you would expect. tables at the top, some top level data structures with lots of ident references. Not sure what you’re asking
queries are still trees, response is still a tree, using built-in merge, which in turn uses tree->db
thus the desire to build the queries with defui, even if there isn’t UI in the defui
the trick is the callback in send accepts a query to use for normalization…so you tell it to use that instead of the default (which is the root UI query)
oh, I thought you were saying that was a bad thing that your technique does not make you do
huh interesting, I'll have to come back to this when I re-think my data fetching, which I've been meaning to clean up
yeah, so the helper puts the desired query (which has metadata for norm) into a “ready to load” queue. The send gets called, pulls the query off, shoots it to the server, gets the response, then gives the response and query to the callback.
really useful for prefetching too, where the current UI may not even have the stuff you want to fetch
I have that sort of working with process-roots
but I haven't really fleshed out that story yet
@tony.kay: this is my read function so far, read-remote
looks for specific keys to make remote https://gist.github.com/jlongster/cd5df87a046c6505f8ed
the UI will ask for those and if they aren't loaded yet they just won't exist. what I really need to do is implement "paging" where I request an initial amount of transactions and load more on demand, but shouldn't be hard
Can anybody help. I’m trying to update AST for remote fetch, ended up with following minimum code that doesn’t work:
(defn read [{:keys [ast] :as env} key params]
{:remote (assoc ast :query [:content "remote-id"])})
((om/parser {:read read}) {:state {}} [:content] :remote)
Last line returns [:content]
while I’ve expected to get updated AST like [:content "remote-id”]
so I can use it in my send
function. Am I doing something wrong?I'm seeing a "No queries exist for component path"
error when going three levels deep on component nesting, after performing a transact!
. The mutation succeeds but then this error. Is there something obvious I could look at? Using the routing advice here - http://anmonteiro.com/2016/02/routing-in-om-next-a-catalog-of-approaches/ - and then once of the routes has multiple components and it's one of those components that is causing the issue.
I've resolved the issue; seems like passing in state cuts the component off from the reconciler, so I improved the 'logic' in a couple of the reads, which allows me to nest queries (as I'd kind of expect anyway) but this means calling the parser inside a read. Is that kosher?
Question motivated from a clojurescript/om issue: How does one refer to external/pureJS react components within clojurescript that were written in JSX/ES6 syntax?
http://stackoverflow.com/questions/35696865/accessing-a-browserify-babel-es6-module-with-es5-syntax
hi channel! What are the trade-offs of storing defrecord instances in om.next’s app-state?
If I understand correctly, http://anmonteiro.com/2016/02/routing-in-om-next-a-catalog-of-approaches/, routing leads to unnecessary nesting . e.g. using Unions we have :route/data {:routing-key {actual-query}}
. What if I would like the data to be available directly under the actual-query
keys e.g. for {:auth/login [:some-key]}
, I would like to have data present under :auth/login
directly. Can I do that ?
@tawus: There are several approaches mentioned in that article, union queries is just one of them. A more popular choice seems to be set-query! which would insert the actual query where you want it, as you described.
@tawus: what @danielstockton said; I've ended up 'riffing' on the implementation suggestions in that article
If you write a mutation that doesn't work as intended then this library will let you know about the problem - in your browser as soon as it happens. Also useful for getting your initial state normalized:
@danielstockton: this is still one :route/data ... May be recursive-remote can play a part here
@tawus: if you're going to do routing, you'll have to aggregate your routes under a common key
there's really no way around that
regardless of the approach you end up choosing
recursive parsing surely helps there
what's the problem you're having?
@anmonteiro : If X and Y are two components for routing. X has a query`[{:x-data [:a :c]}` and component Z, which is nested inside Y, needs :x-data
. It can only access it using links. but if X Y are under :route/data
, :x-data
is not top level and can’t be accessed as a link.
@tawus: so what's stopping you from moving :x-data
to the top-level and querying with a link in X and Z?
Hmm… that seems to be a good idea and proves that I have to go back to the tutorials again 😞 I’ll check out this approach. Thanks, really appreciate it!
Any thoughts on how to idiomatically handle db->tree
, but also have parameterized queries in parts of the query?
Specifically, how would one handle something like this: https://github.com/omcljs/om/wiki/Remote-Synchronization-Tutorial#building-a-simple-auto-completion-widget, but for a collection auto-completion widgets.
That is, how would you handle children with parameterized queries, and keep context so you know how to merge in novelty?
May I ask again, maybe somebody can help. I’m trying to update AST for remote fetch, ended up with following minimum code that doesn’t work:
(defn read [{:keys [ast] :as env} key params]
{:remote (assoc ast :query [:content "remote-id"])})
((om/parser {:read read}) {:state {}} [:content] :remote)
Last line returns [:content]
while I’ve expected to get updated AST like [:content "remote-id"]
so I can use it in my send
function. Am I doing something wrong?What’s the shape of the response from a server-side mutation supposed to look like? I have a bare bones example, that sends back a response that looks like this:
{message {:keys [:message], :result {:message Changed by mutation on server!, :description Description set on server, initial load., :sender Server guy}}}
that whole thing gets merged into my client side state, instead of the :message, etc keys getting updated. So component doesn’t render with any update
@jeremyraines: Why :result
and not :value
?
@artemyarulin: try (assoc ast :query [:content] :params {:id "remote-id"})
I’m not sure, here’s my mutation fn on the server side
@bnoguchi: Thanks, I’ll try!
(defmethod mutate :default
[{:keys [state] :as env} key params]
{:value {:keys [:message]}
:action
(fn []
(swap! state assoc :message "Changed by mutation on server!")
(swap! state assoc :sender "Server guy"))})
@jeremyraines: Are you sending just the mutation(s) or are you also querying for keys to be read again after the mutations have been applied?
just the mutation. But it’s from inside a component where those keys are part of the component’s query
clojure
(defui HelloWorld
static om/IQuery
(query [this]
'[:message :description :sender])
Object
(render [this]
(let [props (om/props this)
msg (:message props)
desc (:description props)
sender (if-not (= (:sender props) :not-found)
(:sender props)
"Unknown")]
(dom/div #js {:onClick (fn [_] (om/transact! this '[(message)]))}
(str msg ": " desc " -- " sender)))))
@artemyarulin: actually don't set query. try (assoc ast :key :content :params {:id "remote-id"})
@jeremyraines: Hmm, that looks about right.
thanks. I’ll try to isolate it further — I’m using compojure-api so maybe something there . . . Everything else works fine though; remote reads, client side mutations, server side mutations; just not merging that state from the server back to the client
@artemyarulin: you could also just do (assoc ast :key [:content "remote-id"])
@jannis: do you know of any online examples that talk to a server besides david’s todomvc?
@jeremyraines: In my copaste experiment, I explicitly add read keys in transactions that include remote mutations. IIRC, Om will not automatically re-run queries against the backend unless this is asked for explicitly. However, that I don't currently know what it does with results returned from the server-side :action
.
yeah — my results appear there but om doesn’t seem to do the right thing with them
I tried explicitly listing the affected keys in the mutation query exp:
(om/transact! this '[(message) :message :sender])
still no luck. It doesn’t even seem to send anything different to the remote. This is the edn of the request before it’s changed to transit & sent: {:remote [(message)]}
@jeremyraines: Are you asking about returning the result to the client from the result of action?
Maybe? It’s getting returned. I don’t know if it’s the right format. I don’t know what Om expects but what I’m doing is pretty bare bones.
this is what I get back from the server
{message {:keys [:message :sender], :result {:message Changed by mutation on server!, :description Description set on server, initial load., :sender Server guy}}}
that whole thing gets merged into my client side state
rather than the contents of :result
@bnoguchi: Thank you very much, will play with it tomorrow!
wondering if I need to provide a :merge-tree function to my reconciler or something. that would suck
I’m not doing any merging
I give the server reponse directly to OM’s callback
won’t that break reads?
do I need to have different enpoints for reads & mutations?
not at all
OK, thanks. I can probably figure this part out but: where/how do you branch that? different ajax calls for reads and write — to the same endpoint but having different callbacks?
do you use clojure on the backend?
thanks
(def server-parser
(om/parser {:read parser/read :mutate parser/mutate}))
(defn api-handler [req]
(println "incoming: " (:transit-params req))
(res/response (server-parser {} (:transit-params req))))
some inspiration...
the parser is the same story on the backend,
I have some vague memory that the callback normally filters out mutations from client app-state merge...but I'd have to revisit the source to remember.
I’ll just have to remember to never have a piece of state called :result . . .
Yea evade it to, in my case: when transacting something with datomic, clojurescript can't handle the return response
or I am doing something severely wrong
hoo boy:
(defn transit-post [url]
(fn [edn cb]
(println "Sending: ")
(println edn)
(.send XhrIo url
(fn [e]
(this-as this
(let [resp (t/read (t/reader :json) (.getResponseText this))
resp-keys-set (-> resp vec first second keys set)]
(if (resp-keys-set :result)
(let [result (get (-> resp vec first second) :result)]
(cb result))
(cb resp)))))
"POST" (t/write (t/writer :json) edn)
#js {"Content-Type" "application/transit+json"
"Accept" "application/transit+json"})))
simple made some kinda somthin'
that works though
I know the feeling 😄
@jeremyraines: Um...I separate my networking logic from send itself...makes it a bit cleaner
yeah. Still seems pretty bad to have the result stashed in a map which is the value of a map whose key is . . . I guess the mutation “key”? Also fun is that if you quote the mutation query with ` instead of ‘, that key changes
responses are always keyed by the thing that asked the question...in this case a symbol, yes
OK, even if it makes sense, you’re not going to know what that key is when you’re handling an arbitrary response
I’m mean i’m not arguing that it’s wrong. I’m clearly missing several things
it’s just frustrating because the docs don’t really mention this. The example on remote sync is pretty complex
the component sent the question (mutation). The send callback doesn’t know that
@jeremyraines: have you seen @tony.kay 's tutorial yet? that one is currently overdocumented 😁
I don’t think I have . . . & my whole first Google result page of “om.next example” is purple will check it out
I’m trying to understand what you’re doing in your send function. Specifically with om/process-roots. When I give that either my edn payload (what’s going to the server) or the response back from the server, it blows up
was misreading the printed out :rewrite function as an error
but, now that I’ve got that, these are the same:
_ (println "rewrite")
_ (println ((:rewrite (om/process-roots edn)) resp))
_ (println "resp")
_ (println resp)
@dnolen: I think I've found an edge case in db->tree
(db->tree '[[:my-route _]] {:my-route :something} {:my-route :something})
=> {:my-route :something}
whereas:
(db->tree '[[:my-route _]] {:my-route '[:something :else]} {:my-route '[:something :else]})
=> {:my-route nil}
db->tree
will try to resolve the ident in the latter case, but I don't really want it to?
because that might not even be an ident
@anmonteiro: right this is known problem
will do, but one doesn't occur to me right away
@dnolen: suggestion for the issue title appreciated
this case is not ident resolution, I think
or is it?
I think we have some logic for resolving a ident and if get another thing that looks like an ident we resolve again
yep you're right
I'll look into it a bit
@dnolen: right so I was looking in the wrong place
there's even a comment stating what it does
;; support taking ident for data param
I’m still struggling to understand how to handle the response from the server after a server-side mutation. I now understand what the pieces of the response are, and how to find the :result piece which has the updated state I want to merge, but the means of detecting and grabbing it that I’m using (see if the vec’d response’s first entry’s second entry is a map with a :result key) seems really smelly. But it seems like that’s what this commit by @anmonteiro does, on david’s om-next-demo repo. https://github.com/swannodette/om-next-demo/commit/6cd3f894594967d37aa68331902adae69432c967 (That, and removing datomic keys). I just want to make sure that’s just how it is and there’s not some transformation fn or other technique that people use for this that I don’t know about