om

Please ask the channel first, not @dnolen directly!
roti 2017-11-30T09:32:56.000203Z

can I fetch the remote data myself in om? I didn't quite understand how the sync works in om, so I'm thinking to just go with what I know and implement the fetching of data from the servers as mutation functions

roti 2017-11-30T09:34:14.000122Z

(my server also doesn't accept the pull syntax, which I suspect is necessary if I let om to do the sync for me)

roti 2017-11-30T11:27:01.000098Z

@snichme I found the problem, 🤕 , initial rendering is not happening if the data is not present (changing the initial value of the counter to 100 did the trick)

2017-11-30T11:27:57.000318Z

ahh, there was no data in the state?

2017-11-30T11:28:25.000292Z

Seems correct, since, why render if the data isn’t there?

roti 2017-11-30T11:29:41.000098Z

🙂 well one could expect to at least make the initial rendering, and let the component decide what to display when no data is there

roti 2017-11-30T11:31:32.000221Z

but it can be done with non-nil empty values like {} [] or ""

2017-11-30T11:36:15.000217Z

What do you mean with om syncing?

2017-11-30T11:37:23.000150Z

By default there isn’t any syncing, you return a {:remote true} from a mutation which tells it to run on the server. But you can switch it to go regular REST

2017-11-30T11:37:33.000236Z

for example one remote per endpoint

roti 2017-11-30T14:22:31.000237Z

does a component need to include the query of all its children in its own query? because I see that data for a component arrives through props, so it looks to me like a component is responsible to pass the correct data to its children

2017-11-30T14:41:13.000742Z

Yes, parent query children for what data it needs, and should then pass that data to the child in the render method

dyba 2017-11-30T16:30:17.000068Z

Hi everyone, I realized the problem I’m having with Om Next is that the value of (om/props this) changes three times during the course of two API calls to a server.

dyba 2017-11-30T16:31:01.000882Z

The first call to the render method inside my component yields props:

clojure
{:selection/models
 {:id "_model-names",
  :selected nil,
  :label "Select a Model from Registry:",
  :key-fn :value,
  :label-fn :text,
  :options []},
 :selection/model-versions
 {:id "_model-versions",
  :selected nil,
  :label "Select a Model Version from Registry:",
  :key-fn :value, 
  :label-fn :text, 
  :options []}}

dyba 2017-11-30T16:31:31.000613Z

The second call to render yields:

{:selection/models
 {:id "_model-names",
  :selected nil,
  :label "Select a Model from Registry:",
  :key-fn :value,
  :label-fn :text,
  :options
  [{:value "FHA", :text "FHA"}
   {:value "USDA", :text "USDA"} 
   {:value "VA", :text "VA"}]}}

dyba 2017-11-30T16:32:27.000318Z

The third call to render yields:

{:selection/model-versions
 {:id "_model-versions",
  :selected nil,
  :label "Select a Model Version from Registry:",
  :key-fn :value,
  :label-fn :text,
  :options
  [{:value "_SNAPSHOT_", :text "_SNAPSHOT_"}
   {:value "v0_1_0", :text "v0_1_0"}
   {:value "v0_1_1", :text "v0_1_1"}
   {:value "v0_1_2", :text "v0_1_2"}
...]}}

dyba 2017-11-30T16:33:46.000512Z

But if you note, the second call drops the top-level keyword :selection/model-versions

dyba 2017-11-30T16:34:04.000783Z

The third call drops the top-level keyword :selection/models

dyba 2017-11-30T16:36:08.000541Z

And I suspect this is happening here in my app-loop:

(defn app-loop
  [c]
  (go-loop [[{:keys [op] :as m} cb] (<! c)]
    (when (= op :list-model-versions)
      (let [results (<! (reg/list-model-versions "FHA"))
            {model-versions-selection :selection/model-versions} (update-in init-data
                                                                            [:selection/model-versions :options]
                                                                            (fn options-collector [opts coll]
                                                                              (apply conj opts coll))
                                                                            (mapv (fn optionify [s]
                                                                                    {:value s :text s})
                                                                                  (get-in results [:model :items])))]
        (println "list-model-versions in app-loop")
        (cljs.pprint/pprint model-versions-selection)
        (cb {:selection/model-versions model-versions-selection})))
    (when (= op :list-models)
      (let [results (<! (reg/list-models))
            {model-selection :selection/models} (update-in init-data
                                                           [:selection/models :options]
                                                           (fn options-collector [opts coll]
                                                             (apply conj opts coll))
                                                           (mapv (fn optionify [s]
                                                                   {:value s :text s})
                                                                 (get-in results [:model :items])))]
        (println "list-models in app-loop")
        (cljs.pprint/pprint model-selection)
        (cb {:selection/models model-selection})))
    (recur (<! c))))

dyba 2017-11-30T16:37:05.000638Z

I have two callbacks, but each one updates only part of the initial data with the response I get from the API

dyba 2017-11-30T16:38:30.000593Z

This leads me to wonder if I should be retrieving the state of the app from the reconciler and update that instead of init-data

dyba 2017-11-30T16:38:48.000658Z

Any help would be much appreciated! 🙂

dyba 2017-11-30T17:37:54.000733Z

I’ve shrunk my app-loop to this:

(defn app-loop
  [c]
  (go-loop [[{:keys [op] :as m} cb] (<! c)]
    (println "inside app-loop")
    (cljs.pprint/pprint m)
    (when (= op :list-model-versions)
      (let [results (<! (reg/list-model-versions "FHA"))]
        (cb (mapv (fn optionify [s]
                    {:value s :text s})
                  (get-in results [:model :items]))
            {:selection/model-versions [:options]})))
    (when (= op :list-models)
      (let [results (<! (reg/list-models))]
        (cb (mapv (fn optionify [s]
                    {:value s :text s})
                  (get-in results [:model :items]))
            {:selection/models [:options]})))
    (recur (<! c))))
and plan to use a custom merge function in my reconciler to merge the correct state. I have a hunch this might be in line with the way Om Next is architected.

dyba 2017-11-30T17:38:36.000055Z

I’m taking advantage of the second parameter in the callback to pass along the query where the novelty must be introduced

dyba 2017-11-30T19:57:58.000250Z

Well, I finally got this to work and removed the flicker effect I mentioned earlier. The custom merge function did the trick:

:merge (fn [reconciler state novelty query]
                             (cond
                               (contains? query :selection/models)
                               {:keys (conj (get state :selection/models) :options)
                                :next (update-in state
                                                 (conj (get state :selection/models) :options)
                                                 (fn options-collector [opts coll]
                                                   (apply conj opts coll))
                                                 novelty)}

                               (contains? query :selection/model-versions)
                               {:keys (conj (get state :selection/model-versions) :options)
                                :next (update-in state
                                                 (conj (get state :selection/model-versions) :options)
                                                 (fn options-collector [opts coll]
                                                   (apply conj opts coll))
                                                 novelty)}

                               :else
                               {:keys []
                                :next state
                                :query nil}))

1💯
dyba 2017-11-30T19:59:19.000182Z

I have to say, while Om Next is better than Om Now, the uphill climb to learn Om Next is VERY steep

dyba 2017-11-30T20:00:12.000493Z

Please chime in if you think my implementation goes against how Om Next is intended to be used