Fork me on GitHub
#om
<
2016-02-24
>
cjmurphy00:02:48

It is considered a good practice to namespace data values. For example right at the top level app is commonly used. So for example app/selected-button. What to call app? Is it a 'selector', or a 'category', or..?

danielcompton01:02:44

I'm reading https://github.com/omcljs/om/wiki/Quick-Start-(om.next)#a-mutation-function, is there a difference between "thunk", and "function with no arguments"?

hueyp01:02:39

I take them as the same

cjmurphy01:02:16

thunk - no arguments, return value might be important. Used for lazy evaluation of a computation.

7h3kk1d02:02:35

Is this channel used in place of the #C0N43QHHT one?

cjmurphy02:02:25

Yes - for all om - Sean C got rid of #C0N43QHHT channel I thought.

grzm03:02:06

what do you mean, tawus? is there particular difficulty you're having?

tawus03:02:33

e.g. if we are using set-query and the child component is using remote, we have to make changes to the read method for key :route/data.

jimmy03:02:50

hi guys how do we get the current state in componentWillUpdate. I remember that someone has asked it before but I cannot find it ..

tawus03:02:16

@nxqd: om.next/get-rendered-state I think

jimmy03:02:20

@tawus thanks I will try this out. this one looks quite new to me simple_smile

jimmy03:02:19

regarding the problem of channel and tap I asked you yesterday, add ^:once doesn't help. I think it's something else. I will try to find it out later today.

grzm03:02:57

@tawus: can you switch on the route?

tawus03:02:12

I am now able to switch using recursive-remote (from om-next tutorial). Still have to figure out a few things.

jimmy08:02:53

hi guys in om next, to avoid sending nil query to server what should we do ?

jimmy08:02:08

normally in a component we have nil query, we will set the values later ( via query params or whatever ), how do we avoid om to send the nil query when the component first mounted

bnoguchi09:02:43

Running into an “Assert failed: Query violation” with this code. Any insight into why this causes a violation?

(defui X
  static om/IQuery
  (query [this]
    [{:x [:a]}]))

(defui Y
  static om/IQuery
  (query [this]
    [:id]))

(defui Z
  static om/IQuery
  (query [this]
    (conj (om/get-query X) {:z (om/get-query Y)})))

(om/get-query Z)

bnoguchi09:02:24

However, this works by just replacing (om/get-query X) in component Z’s query:

(defui Z
  static om/IQuery
  (query [this]
    (conj [{:x [:a]}] {:z (om/get-query Y)})))

marianoguerra09:02:19

@bnoguchi: try replacing the conj in Z's query with a map or something similar

marianoguerra09:02:35

I got the same error when returning child queries instead of composing them

bnoguchi09:02:33

@marianoguerra: Thanks. Looks like I can’t clobber X’s query’s metadata

bnoguchi09:02:34

Switched it to:

(defui Z
  static om/IQuery
  (query [this]
    (conj (into [] (om/get-query X)) {:z (om/get-query Y)})))

iwankaramazow09:02:55

@bnoguchi: from looking at it: you're stealing the query of component X in component Z

iwankaramazow09:02:41

You can't just take queries from the children

iwankaramazow09:02:25

they need to compose

iwankaramazow09:02:32

example:

(defui X
  static om/IQuery
  (query [this]
	 [:a]))

(defui Y
  static om/IQuery
  (query [this]
	 [:id]))

(defui Z
  static om/IQuery
  (query [this]
	 [{:x (om/get-query X)} {:z (om/get-query Y)} ]))

iwankaramazow09:02:00

"this component just needs what the child needs" is the red flag for 'stealing queries'

bnoguchi10:02:00

@iwankaramazow: What happens if you “steal” a query from a child component, as follows?

(defui Z
  static om/IQuery
  (query [this]
    (conj (into [] (om/get-query X)) {:z (om/get-query Y)})))

marianoguerra10:02:05

@bnoguchi: one of the things is that if you do (om/transact! this <query>) it will give an error

marianoguerra10:02:35

I think the reason is that since the queries don't compose from the "leafts" to the "root" om can't follow the queries to locate the component or something like that

marianoguerra10:02:43

and I'm sure it may cause other problems

grzm13:02:57

@nxqd: can you initialize your query params with some initial values? Would that prevent the nil query issue on mounting?

anmonteiro13:02:24

@nxqd: you're not supposed to have nil queries. If you're using the latest master this should give you an invariant violation. If it doesn't please send me a minimal repro, thanks

jimmy13:02:43

@anmonteiro: thanks for the input, I do have "nil" query like this {:location nil} not actually nil. @grzm I have the same thought, would work on this later today simple_smile

anmonteiro13:02:25

@nxqd: if that nil is a param there's probably no problem. if it's going to be a join things might not work as you expect

grzm14:02:52

I'm trying out anmonteiro's om next devcards (which have been merged into devcards, from what I can tell) http://anmonteiro.com/2016/02/om-next-meets-devcards-the-full-reloadable-experience/

grzm15:02:44

I'm not seeing what I expect as "reloadable". When I make a trivial change to the file and save, all of the counters are reset to 1. I'd expect them to preserve their state. Or am I understanding this wrong?

anmonteiro15:02:41

@grzm: they haven't been merged, what's in devcards is not reloadable

anmonteiro15:02:44

that PR had initially what's now in the repo I linked

anmonteiro15:02:02

but then it ended up being just a patch for making it possible to extend devcards externally

grzm15:02:18

@anmonteiro: so, I should see the state persist for the cases I pass a reconciler to either om-next-root or defcard-om-next. State should not persist if I don't pass a reconciler. Is that correct?

grzm15:02:26

(that's the behavior I'm seeing)

anmonteiro15:02:50

I started toying with defonceing the reconciler inside of the macro

anmonteiro15:02:57

but I didn't have more time to pursue that

anmonteiro15:02:08

and I'm not even sure if it should be opinionated like that

anmonteiro15:02:33

whenever you don't defonce your reconciler and pass it to the macro it will not be reloadable anyways

grzm15:02:33

thanks for confirming. And it's easy enough to pass a reconciler.

rauh16:02:11

Messed up my brackets in a ref with :ui/signup [[:user/by-name] "ar"] and got a vector as the return value of om/db->tree. Not sure if this is considered a bug?

anmonteiro16:02:21

@rauh: was the db->tree result :ui/signup [[:user/by-name] "ar"] ?

rauh16:02:57

@anmonteiro: Nope, it was [{<query-result>}, {<query-result>}]

anmonteiro16:02:21

and what should it have been?

rauh16:02:43

I thought it would always return a map, no?

anmonteiro16:02:33

it can return a vector

rauh16:02:30

I see, then ignore what I said. Sorry for the noise. Still all new to me simple_smile

iwankaramazow19:02:20

@grzm: confirmed this works :hugging_face:

(defn custom-merge-tree [a b] (if (map? a) (merge-with into a b) b))

(defonce reconciler
  (om/reconciler
   {:state app-state
    :parser (om/parser {:read p/read :mutate p/mutate})
    :send (utils/transit-post "/api")
    :merge-tree custom-merge-tree
    }))

iwankaramazow19:02:16

basically you don't overwrite existing key/values with this merge

iwankaramazow19:02:43

might come in handy when building a stairway to cache heaven

jamesmintram21:02:27

Hey guys, I have another question. I have a list of items, one of which is selected. This is defined in my original set of data as follows:

(def init-data
  { :list/users {:selected-user [{:ID 1 :selected true}]
                 :users [{:ID 0 :userName "Jimmy"}
                         {:ID 1 :userName "Robby"}
                         {:ID 2 :userName "Bobby"}]}})
Which correctly adds :selected true to Robby when normalised. Now I cannot figure out how to change the selected user - I have tried a few things without success - So thought I’d ask here, as it should be pretty trivial.

jamesmintram21:02:29

I guess another point to ask, is that even the right approach to take?

anmonteiro21:02:29

@dnolen: eliding data-paths is a parser option, but e.g. default-ui->props relies heavily on the component's path to pass the appropriate props to the component that's re-rendering

dnolen21:02:50

@anmonteiro: data path elision is a hack

anmonteiro21:02:56

I'm looking to understand the rationale behind this option: is this supposed to be server thing?

dnolen21:02:59

if you use it you better be ready for everything to break

anmonteiro21:02:06

I can live with that

anmonteiro21:02:17

I'm still working on the query stuff

anmonteiro21:02:26

and I'm also relying on component paths

dnolen21:02:34

we should be able to remove it when data path annotation happens by using the query

anmonteiro21:02:46

so I was wondering if it's OK for stuff to break if path ellision was turned on simple_smile

dnolen21:02:50

I might leave it in there just for the weird cases where it’s desirable for some weird perf reason

dnolen21:02:09

yes breakage can be expected if you use it

anmonteiro21:02:39

btw, after 3 failed implementation attempts, I think I'm going somewhere

anmonteiro21:02:07

kudos to you for the indexer stuff, this thing is powerful 😉

anmonteiro21:02:33

I might have something to show soon. should I open a PR for it? link you the commit in my branch?

cjmurphy22:02:42

@jamesmintram: You have to write your own mutate method that is in your parser and call it with om/transact!.

jamesmintram22:02:56

@cjmurphy: So the current mutate method looks like this:

(defmethod mutate 'users/select
  [{:keys [state] :as props} _ {:keys [ID]}]
  {:value {:keys [:list/users :selected-user]}
   :action (fn []
     (swap! state assoc-in
            [:list/users]
            {:selected-user {:ID ID :selected true}}))})

cjmurphy22:02:23

You might need the last one to be :selected false as well.

anmonteiro22:02:43

@jamesmintram: since your data is normalized at that point you need to put an ident under the :selected-user key

anmonteiro22:02:32

the :selected true might not even be necessary

jamesmintram22:02:57

@anmonteiro: So I tried that as well (using the mutate below) - and it correctly updates the :selected-user value in the state, but that doesn’t propagate to the associated user in :list/users

(defmethod mutate 'users/select
  [{:keys [state] :as props} _ {:keys [ID]}]
  {:value {:keys [:list/users :selected-user]}
   :action (fn []
     (swap! state assoc-in
            [:list/users]
            {:selected-user [:user/by-id ID]}))})

anmonteiro22:02:59

@jamesmintram: because that's just a reference

cjmurphy22:02:05

Needed is something that checks that mutates have not taken your state away from normalized, and pops up a message in the browser to say where the problem is. I've written a library does that - will release it tomrrow or very soon. But for now manually look at it and see if Idents are everywhere they should be, which is everywhere.

anmonteiro22:02:43

you then need to update the actual user data structure with whatever new fields you want

jamesmintram22:02:26

@anmonteiro: Hah! Ok, that would probably explain it simple_smile - I will go away and re-read the docs. @cjmurphy thanks for the advice - I will check it out!

anmonteiro22:02:02

@jamesmintram: what I mean is go ahead and update the entry under :user/by-id ID

anmonteiro22:02:14

which is where your "entities" live in a normalized state

jamesmintram22:02:59

Ah Ok - so in my case, the :selected-user reference is actually redundant - and I am better off using assoc/dissoc on the normalized data.

cjmurphy22:02:00

Where the entities live is the 'tables' part of default db format.

anmonteiro22:02:06

what is redundant IMO is the :selected key under the user.

anmonteiro22:02:02

since it'll cause you pain once you want to select another user... You'll have to deselect the currently selected

anmonteiro22:02:08

2 operations instead of one

jamesmintram22:02:23

That is what I originally thought, but then I ended up down this path. So an ideal solution would involve each User component checking itself against the :selected-user ID - and if it matches do something special (in this case, apply a CSS class)

anmonteiro22:02:18

Without any other info that's probably what I'd do