untangled

NEW CHANNEL: #fulcro
adamvh 2017-06-07T03:19:18.025271Z

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

adamvh 2017-06-07T03:20:04.030213Z

i think what i was missing is how untangled uses ident to do all of this

claudiu 2017-06-07T06:11:30.142558Z

@tony.kay By no-op you mean it should not work on the server ?

claudiu 2017-06-07T06:12:01.146453Z

The flow I’m trying to get is:

claudiu 2017-06-07T06:14:32.164929Z

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

claudiu 2017-06-07T06:15:12.169841Z

basically dropping the new-client started-callback.

claudiu 2017-06-07T06:16:20.178846Z

probably a naive approach on server, was trying to implement like:

claudiu 2017-06-07T06:18:27.195246Z

(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)))

claudiu 2017-06-07T06:18:51.198333Z

Can you help me out with a suggestion on how to get this flow with untangled ?

claudiu 2017-06-07T06:21:11.217196Z

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 ?

tony.kay 2017-06-07T19:58:05.799627Z

@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.

tony.kay 2017-06-07T19:58:36.810864Z

Om has a function called tree->db that is the essential workhorse for normalization

tony.kay 2017-06-07T19:59:33.830652Z

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.

tony.kay 2017-06-07T19:59:58.839477Z

@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.

adamvh 2017-06-07T20:01:39.877700Z

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! 🙂

tony.kay 2017-06-07T20:02:59.905658Z

@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.

tony.kay 2017-06-07T20:03:08.908938Z

@adamvh welcome

adamvh 2017-06-07T20:03:20.913270Z

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?

adamvh 2017-06-07T20:03:37.919213Z

or just generally to operate on whatever it gives me

adamvh 2017-06-07T20:04:05.928877Z

or is that a little outside the scope of data-fetch

tony.kay 2017-06-07T20:04:42.941497Z

@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.

tony.kay 2017-06-07T20:05:41.962405Z

@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.

tony.kay 2017-06-07T20:06:14.973446Z

You could also just add functions to the server layer to speak to your app, since they are usually pretty thin

adamvh 2017-06-07T20:06:34.979987Z

yeah, i had my eye more on hitting third-party API endpoints that don't speak EDN

tony.kay 2017-06-07T20:06:38.981163Z

pre-existing REST services: usually make a network obj for client

tony.kay 2017-06-07T20:07:05.990110Z

Also note that you can specify “which” remote, and can have more than one networking object installed

tony.kay 2017-06-07T20:07:18.994305Z

loads and mutations both support that

adamvh 2017-06-07T20:08:28.017735Z

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?

tony.kay 2017-06-07T20:08:34.019783Z

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...)
  ...)

tony.kay 2017-06-07T20:09:51.045124Z

in the network namespce there is an UntangledNetwork protocol. Implement that. Mainly send

tony.kay 2017-06-07T20:09:59.047448Z

see the source of the built-in one for ideas.

tony.kay 2017-06-07T20:10:53.065595Z

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.

tony.kay 2017-06-07T20:11:28.077606Z

for loads, load supports a :remote option that is just the name you choose for the remote

tony.kay 2017-06-07T20:11:54.086214Z

the default remote is just called :remote

tony.kay 2017-06-07T20:12:08.090867Z

which is why you normally use that name in defmutation

adamvh 2017-06-07T20:12:38.100833Z

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?

tony.kay 2017-06-07T20:12:53.105864Z

https://cljs.github.io/api/cljs.core/js-GTclj

tony.kay 2017-06-07T20:13:09.111117Z

remember that there is an easy way to convert js data to clj

tony.kay 2017-06-07T20:13:35.119732Z

Docs: the dev guide should have something on advanced networking already…welcome to add to it

adamvh 2017-06-07T20:14:05.129435Z

ok, wasn't sure if i'd be stepping on toes by submitting pull-reqs to the dev-guide 🙂

tony.kay 2017-06-07T20:14:52.144683Z

oh, I guess it doesn’t…yeah, that’s the place to contribute that

tony.kay 2017-06-07T20:15:12.151140Z

The M section would prob be the place

tony.kay 2017-06-07T20:15:26.155991Z

like M50-Using-REST ?

tony.kay 2017-06-07T20:15:39.160510Z

or Multiple-Remotes

adamvh 2017-06-07T20:16:39.179919Z

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

adamvh 2017-06-07T20:16:49.183341Z

err

adamvh 2017-06-07T20:16:52.184498Z

df/load

tony.kay 2017-06-07T20:16:52.184561Z

Yeah, I’d love to get rid of those refs

adamvh 2017-06-07T20:17:26.195699Z

and the solutions don't refresh on load from the server (you have to type in the text box to trigger re-render)

adamvh 2017-06-07T20:17:49.203078Z

alright, well, if i find the time i'll try and submit some pull requests

tony.kay 2017-06-07T20:18:09.209004Z

Note: I’m working on a combo lib that integrates the dev guide

tony.kay 2017-06-07T20:18:31.216199Z

I may have already made some fixes…you’d want to open an issue and point to the problems so I can look

adamvh 2017-06-07T20:18:41.219630Z

ok, will do

adamvh 2017-06-07T20:21:29.274881Z

i think i'll write one issue with everything i've noticed in this file

tony.kay 2017-06-07T20:22:14.289462Z

great, thanks

claudiu 2017-06-07T20:23:31.315266Z

@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. :)

tony.kay 2017-06-07T20:24:16.330156Z

yeah, how would I implemnent load on the server? The networking is totally different.

tony.kay 2017-06-07T20:24:34.336407Z

so it is just a stub so it doesn’t crash

claudiu 2017-06-07T20:41:23.673425Z

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.

tony.kay 2017-06-07T20:44:23.732167Z

I see. Calling the server parser directly in the initial-state should work. all you need is a tree of data there

tony.kay 2017-06-07T20:44:52.741593Z

As long as the query matches (so normalization works)

tony.kay 2017-06-07T20:45:15.749262Z

now that could be a problem, I guess, since you might not want the query there.

tony.kay 2017-06-07T20:45:45.759606Z

I guess you could use merge-state! manually instead

claudiu 2017-06-07T20:50:57.863986Z

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.

tony.kay 2017-06-07T20:52:13.888909Z

k, let me know what you do. I’d be interested in adding that to the devguide as well

claudiu 2017-06-07T20:58:14.008813Z

ok 🙂