Fork me on GitHub
#fulcro
<
2017-11-04
>
vinnyataide14:11:28

I'll try to implement these live data funcs in my app

vinnyataide14:11:39

it's planned since the beginning and it kinda works in my head

fatihict15:11:20

I like the idea to put follow-on reads in defmutation šŸ˜„

tony.kay19:11:11

@vinnyataide sounds interesting, but I have no idea what you mean šŸ™‚

vinnyataide19:11:47

@tony.kay live data functionality like meteor

tony.kay19:11:58

oh, I see, right

tony.kay19:11:08

You using Datomic?

tony.kay19:11:07

@vinnyataide The method I was using was this: 1. Send a subscribe from the client (as a mutation) with the graph query of interest (as a parameter). Stash the query (on the client) so that the push notifications know what it is (and still have the component metadata on the query for normalization). You could safely store this in app state, for example. 2. on the server, associate the subscription with the websocket client id 3. Run the query and push the result to the client. The client uses the stashed query to merge/normalize it. 4. On the server, use something like clojure walk to pull out all of the :db/id from the tree of data from (3). Put those in the ā€œwatch setā€ for that subscription 5. Add a tx log watcher to datomic. If any of those IDs appear in the tx result, repeat (3) and update the watch set in (4) Worked fineā€¦there is obviously some polishing from there, but it was surprisingly little code.

vinnyataide20:11:13

Didn't thought about the w alk method

mss21:11:27

hey all, are there any resources out there about best practices writing parsers in fulcro? some semi-complicated real world examples would be extremely helpful. Iā€™m a little stuck in the weeds with how to proceed actually building an application using fulcro, as I canā€™t figure out exactly how to structure my parsers for anything beyond toy applications

claudiu21:11:58

@mss What exactly do yo mean by parsers in fulcro ?

claudiu21:11:45

for me the video tutorials really helped get a bit of a overview of how work https://fulcrologic.github.io/fulcro/docs.html

mss22:11:37

I guess my hangup is something like: given that youā€™re trying to compose all child componentsā€™ queries into a root query, how do you decompose the query in that root read fn in the parser and pass those query fragments down to other parsing functions that can actually service the query fragment?

mss22:11:19

like for a totally contrived example, say I have some ui components that look like the following:

(defui NavbarSettingsDropdown
  static om/IQuery
  (query [this]
    [:user/email])
  Object
  (render [this]
    (let [{:keys [user/email]} (om/props this)]
      (dom/p nil email))))

(def navbar-settings-dropdown (om/factory NavbarSettingsDropdown))

(defui NavbarSignInPrompt
  static om/IQuery
  (query [this]
    [:authentication-request/is-loading?])
  Object
  (render [this]
    (let [{:keys [authentication-request/is-loading?]} (om/props this)]
      (if is-loading?
        (dom/p nil "Loading...")
        (dom/button nil "Sign in")))))

(def navbar-sign-in-prompt (om/factory NavbarSignInPrompt))

(defui Navbar
  static om/IQuery
  (query [this]
    [:something
     {:navbar-sign-in-prompt-data (om/get-query NavbarSignInPrompt)}
     {:navbar-settings-dropdown-data (om/get-query NavbarSettingsDropdown)}])
  Object
  (render [this]
    (let [{:keys [user/authenticated? navbar-sign-in-prompt-data navbar-settings-dropdown-data]} (om/props this)]
      (if authenticated?
        (navbar-settings-dropdown navbar-settings-dropdown-data)
        (navbar-sign-in-prompt navbar-sign-in-prompt-data)))))

(def navbar (om/factory Navbar))

(defui Body
  static om/IQuery
  (query [this]
    [:something]))

(defui RootComponent
  static om/IQuery
  (query [this]
    [{:body-data (om/get-query Body)}
     {:navbar-data (om/get-query Navbar)}])
  Object
  (render [this]
    (let [{:keys [navbar-state]} (om/props this)]
      (navbar navbar-state))))
what would my read fns look like? I could do something like:
(defmulti read om/dispatch)

(defmethod read :body-data
  [env key params])

(defmethod read :navbar-data
  [env key params])

(defmethod read :navbar-sign-in-prompt-data
  [env key params])

(defmethod read :navbar-settings-dropdown-data
  [env key params])
but forwarding the fragments pulled up into the root query down to those other read fns feels a little wrong, and I canā€™t quite piece together what om/fulcro api methods I might use to assist in that if anyone has any tips Iā€™d love to hear more

cjmurphy23:11:56

@mss: with Fulcro you don't have reads on the client - mutations change the state and your components pick up that state.

mss23:11:01

isnā€™t there still the read-local option you pass to the client?

cjmurphy23:11:04

The components you have there seem like they are 'one ofs', in which case there is only one ident for each 'class', and using InitialAppState will be able to get some of the state in place.

cjmurphy23:11:56

@mss: I have never heard of read-local sorry šŸ˜œ

cjmurphy23:11:57

I know with Om Next I did have to compose all the components at the root. Or to put it another way when I debugged the state and found something not there I would add that component (get-query MyComponent) in the root query. Have not needed to do that with Fulcro so far.

mss23:11:36

interesting. seems like Iā€™m coming at this from the totally wrong mental model since I started by diving into om

cjmurphy23:11:00

So data will either come from load (also note load-action) or from InitialAppState.

cjmurphy23:11:44

Use (dump) from user namespace to make sure it is all there and normalized properly.

cjmurphy23:11:25

Then the only problem left is rendering and sometimes having to use follow on reads.

cjmurphy23:11:28

The model is the same as Om Next, just need to embrace load and InitialAppState.

mss23:11:11

yeah that seems to be what I was missing. really appreciate the help!

cjmurphy23:11:47

@mss: Just looking at my code I have a defrouter in the Root. Another thing to look at is the initial load done from :started-callback. I think that completes important areas to look at from the client perspective.