ok, so what (df/load app :key Comp)
does is ship some EDN off the server that looks like {:key (om/get-query Comp)}
. the server then sends back a vector of things. untangled does #(swap! app-state assoc-in (ident Comp %) %)
for every element in this vector, and it also puts (map %(ident Comp %) result)
into :key
at the top-level of the app-state
i think what i was missing is how untangled uses ident
to do all of this
@tony.kay By no-op you mean it should not work on the server ?
The flow I’m trying to get is:
On initial load, on the server, 1) generate the db with get-initial-app 2) set the current route 3) populate the db with the server data 4) render-to-str the app 5) dump the db in the html 6) client loads the pre-populated db from the html
basically dropping the new-client started-callback
.
probably a naive approach on server, was trying to implement like:
(def app-state (uc/get-initial-state ui/Root {}))
(def parser (om-server/parser {:read api/api-read :mutate api/api-mutate}))
(def ui-parser (om-next/parser {:read plumbing/read-local :mutate plumbing/write-entry-point}))
(def reconciler (om-next/reconciler {:state (atom app-state)
:send (fn [d cb] (cb (parser {} (:remote d))))
:parser ui-parser}))
(df/load reconciler :all-items ui-root)
(def app-str (dom/render-to-str (ui-root app-state)))
Can you help me out with a suggestion on how to get this flow with untangled ?
Also noticed that new-untangled-client ignores the :initial-state
if the root component has uc/InitialAppState
is there any change this will change in the future ? To If I specify it then it will be used ?
@adamvh Untangled doesn’t do normalization. Om does. Untangled merges the result from the server using Om’s merge (which in turn uses the original query, which contains component metadata, to normalize the return value). The return value can be a vector or a singleton…up to the server.
Om has a function called tree->db
that is the essential workhorse for normalization
If you look at the metadata on the query, you’ll see that get-query
hangs the component on the node of the query that was generated by that component. This allows tree->db
to figure out (recursively) which components to use to normalize the entire tree of data from the server into the UI database.
@claudiu Yes. You’re on the server. There is nothing to load. You’re doing server-side pre-rendering, not running the entire app there.
well, regardless of which layer of the stack is doing what, i think i understand what's happening, at least in the simple case of the dev-guide, so thanks for your patience and the nice video! 🙂
@claudiu You could generate a data structure and emit that into the page as embedded javascript and do some magic to merge that in…but as far as I’m concerned Untangled is not meant to be run on the server this way…just initial render. You have to wait for the JS to load before anything happens. If you know something in advance on the server you could technically embed it into initial-state
to get an initial render that looks pre-filled.
@adamvh welcome
if the server doesn't know how to respond in EDN, is there somewhere i can hook into the df
mutations to EDN-ize whatever it gives me?
or just generally to operate on whatever it gives me
or is that a little outside the scope of data-fetch
@claudiu The initial-state behavior is for bw compat. Once you embed it in a component, it overrides the option and issues a warning. But you can put logic in the initial-state
function of your root component.
@adamvh There are a couple of approaches. The EDN layer is at the networking. You can plug in a custom network object into client and do what you want with the EDN of the client and the responses of the server.
You could also just add functions to the server layer to speak to your app, since they are usually pretty thin
yeah, i had my eye more on hitting third-party API endpoints that don't speak EDN
pre-existing REST services: usually make a network obj for client
Also note that you can specify “which” remote, and can have more than one networking object installed
loads and mutations both support that
yea, that seems like the cleanest way to do that. where would i look for info on network objects and hooking them for different remotes?
if you’re using defmutation
:
(defmutation update-thing [{:keys [param]}]
(action [{:keys [state]}] ...local update...)
(name-of-remote-1 [env] ...stuff to send to remote-1...)
(name-of-remote-2 [env] ...stuff to send to remote-2...)
...)
in the network
namespce there is an UntangledNetwork protocol. Implement that. Mainly send
see the source of the built-in one for ideas.
you’ll receive the data to send, and the callback to call with the response. EDN for both. You’re responsible for talking to the server however you want, and translating the response back to EDN that makes sense for merge.
for loads, load
supports a :remote
option that is just the name you choose for the remote
the default remote is just called :remote
which is why you normally use that name in defmutation
yea, will check it out. btw, if i take the time to figure out some of this stuff for myself and write up my understanding, is there some doc for which pull requests would be welcome?
remember that there is an easy way to convert js data to clj
Docs: the dev guide should have something on advanced networking already…welcome to add to it
ok, wasn't sure if i'd be stepping on toes by submitting pull-reqs to the dev-guide 🙂
oh, I guess it doesn’t…yeah, that’s the place to contribute that
The M section would prob be the place
like M50-Using-REST ?
or Multiple-Remotes
the J section is also using df/load-data
in the exercises and solutions - given that i just worked through that, i was thinking i might update the solutions to use df/load-data
err
df/load
Yeah, I’d love to get rid of those refs
and the solutions don't refresh on load from the server (you have to type in the text box to trigger re-render)
alright, well, if i find the time i'll try and submit some pull requests
Note: I’m working on a combo lib that integrates the dev guide
I may have already made some fixes…you’d want to open an issue and point to the problems so I can look
ok, will do
i think i'll write one issue with everything i've noticed in this file
great, thanks
@tony.kay thank you. Will play around with it a but more and see if I can find a way to reuse the code and populate the db. There were some render cobditionals in the df/load and though maybe there is a easy built in way. :)
yeah, how would I implemnent load
on the server? The networking is totally different.
so it is just a stub so it doesn’t crash
Think while playing with om-next managed to get it working with reconciled :send
on the client it was a http call, on the server it was a call to the server parser directly. Was just a simple get from atom test so not sure if it has any gotchas.
I see. Calling the server parser directly in the initial-state
should work. all you need is a tree of data there
As long as the query matches (so normalization works)
now that could be a problem, I guess, since you might not want the query there.
I guess you could use merge-state!
manually instead
Will play around with it more. It’s a important for my project since i have a few public pages and it really helps with seo & loadtime.
k, let me know what you do. I’d be interested in adding that to the devguide as well
ok 🙂