Fork me on GitHub
#om
<
2016-05-30
>
adammenges01:05:56

Trying to learn om.

adammenges01:05:14

I've got a mostly empty project created by lein new figwheel om -- --om, and I'd like to add a draggable element to it, something like this done in straight js: (https://jsfiddle.net/tovic/Xcb8d/)

adammenges01:05:24

I really appreciate any help in trying to understand how this works

rgomezcasas13:05:51

Hey People! I have a question… I don’t know if it’s a bug or my fault (surely it’s my fault :P)… I have a root component which om/get-query is: [:current-route {:some-entity/new [:id :name]}] and then a subcomponent which om/get-query is: [{:some-entity/new [:id :name]}]. Every time I’m doing a transact on the child element, this error occurs Uncaught #error {:message "No queries exist for component path (my-project.core/Root my-project.pages.create-entity/CreateEntityPage)", :data {:type :om.next/no-queries}} (The error is triggered, but the transact is done and all the app works fine) I looked for this error and I found some issues on github, but all are closed now, so I suppose I'm doing something wrong... Anybody has any idea? Thanks! 🙂

ag13:05:05

@rgomezcasas: I bet you’ve stumbled upon the exact same thing that made me feel stupid just yesterday. Look into (om/process-roots), if you search for it in Tony Kay’s tutorial, you’ll find that. Also I suggest you to look for it in om-next's source, the docstring is helpful

rgomezcasas13:05:32

Okey, I’m gonna look in!!

anmonteiro13:05:55

@rgomezcasas: that error has nothing to do with process-roots it is exactly what is says, there’s no path in the queries from Root to CreateEntityPage

anmonteiro13:05:13

most likely your queries are not correctly composed (e.g. via get-query)

rgomezcasas13:05:12

I tried to do: [:current-route {:create-page {:some-entity/new [:id :name]}}] but doing this I do not receive the query “some-entity/new” result

rgomezcasas13:05:07

So, that’s the computed and the query is [:current-route {:create-page (om/get-query CreateEntityPage)}]`

anmonteiro13:05:31

what about the CreateEntityPage component’s query?

rgomezcasas13:05:42

The CreateEntityPage query is: [{:some-entity/new (om/get-query Entity)}]

rgomezcasas13:05:12

And the Entity query is: [:id :name :description :reward :application-id]

anmonteiro13:05:29

@rgomezcasas: 2 more questions: 1. which Om version are you using? 2. are you passing props down correctly?

rgomezcasas13:05:55

The version is 1.0.0-alpha36

rgomezcasas13:05:22

And maybe I’m passing incorrectly the props down

rgomezcasas13:05:44

I’m passing down all the props

rgomezcasas13:05:32

Inside a let in the render part I have current-page (om/factory (current-route-page))

anmonteiro13:05:43

by all the props you mean you’re always passing (om/props this) down?

rgomezcasas13:05:47

And then I’m rendering like: (current-page (om/props this))

anmonteiro13:05:55

so that’s what’s wrong

anmonteiro13:05:12

you need to select the key in props that corresponds to the path in the query

rgomezcasas13:05:15

Ok, so I only need to pass the “current page” props?

rgomezcasas13:05:26

Ok, I’m going to try!

anmonteiro13:05:29

once you do that the error should go away

rgomezcasas13:05:59

Ok, so, I let the root query as [:current-route {:current-page (om/get-query CurrentPageComponent)}] and only pass down the current-page props?

anmonteiro13:05:20

there’s nothing wrong with your query structure

anmonteiro13:05:27

the queries are correctly composed

anmonteiro13:05:09

but as a rule of thumb, if you have a query [{:current-page (om/get-query CurrentPageComponent)}], you’ll want to pass (:current-page (om/props this)) down to the CurrentPageComponent

rgomezcasas14:05:58

@anmonteiro: I just changed the code as you said, but now the read method it’s not executed never, so in the Root get-props I’m receiving {:current-route :create-entity, :current-page {}}

anmonteiro14:05:25

@rgomezcasas: the changes I suggested shouldn’t impact anything in the read method

anmonteiro14:05:35

it might be a whole different bug altogether

rgomezcasas14:05:11

I’m going to do some debug! 🙂

adamfrey14:05:25

I’m trying to understand the default-migrate function included in Om.next. Using it gives me a result that is surprising to me. My app state has looks like

{:place/by-id
 {17592186045441
  {:db/id 17592186045441,
   :place/name “name"}…} :leaflet/map-obj #object[Object [object Object]]}
and my component that renders Places has this query [:db/id :place/name [:leaflet/map-obj _]] using the link strategy to pull in the top level leaflet key into each Place. But when I create a new Place and the default-migrate function is called my app state turns into
{:place/by-id
 {17592186045441
  {:db/id 17592186045441,
   :place/name “name”,
   :leaflet/map-obj #object[Object [object Object]] }…}}
so the top level object is pulled completely out of the key where it was and placed into each Place object in the app state. I know this happens because default-migrate calls db->tree internally which resolves links, but is what I just described desired migration behavior by default?

rgomezcasas15:05:56

@anmonteiro: after some debugging I found this error core.cljs:9857 Uncaught Error: No method in multimethod ‘my-project.infrastructure.parser/read' for dispatch value: :current-page

rgomezcasas15:05:25

Is treating this key as a query, inside look for the inside ones

rgomezcasas15:05:59

I assume I should create another read with that key and inside of these raise the others queries?

anmonteiro15:05:34

@rgomezcasas: can’t say anything without more information

anmonteiro15:05:01

e.g. normalized vs. denormalized data, using db->tree or not, recursive parsing or not

rgomezcasas15:05:26

Ok, so my question is… I have a similar approach to https://anmonteiro.com/2016/02/routing-in-om-next-a-catalog-of-approaches/#routing-with-union-queries, but my “pages” have queries that goes to the read fn, so I can’t get the keys directly from the state

rgomezcasas15:05:35

Is there a way to call these reads from another read?

anmonteiro15:05:31

I’m not sure what you’re trying to say

rgomezcasas15:05:33

I don’t know how to explain xD

rgomezcasas15:05:43

My root element has this computed query

[:current-route
 {:current-page-queries
  [{:some-entity/new [:id :name :description]}]}]

rgomezcasas15:05:15

So, this will trigger the defmethod read :current-page-queries

rgomezcasas15:05:54

Is there a way to trigger the defmethod read : some-entity/new from the : current-page-queries read?

anmonteiro15:05:00

@rgomezcasas: you can use recursive parsing. in the env argument for your read method, there’s a :parser key

anmonteiro15:05:26

which allows you to recurse on the parser

anmonteiro15:05:42

the signature is env query target

rgomezcasas15:05:56

So, I’ll return a map from my “query” using the recursive parsing

anmonteiro15:05:27

I don’t know what that means

rgomezcasas15:05:01

In the :current-page-queries I receive this query [{:promo/new [:id :name :description]}]

rgomezcasas15:05:42

But in another page I could receive [:some-stuff :another {:some-entity/new [:id :name :description]}]

anmonteiro15:05:01

you probably want to recurse on the current route, if that’s what you’re asking

rgomezcasas16:05:13

Ok, It’s all ok now, thanks, @anmonteiro! I’ll buy you a beer when you come to bcn for the fullstackfest 😛

rgomezcasas16:05:26

The read method ended being:

(defmethod read :current-page-queries
  [{:keys [query parser] :as env} _ target]
  {:value (parser env query target)})

bert16:05:28

Hi folks - I'm working through my first om next app right now, and found a surprising case where the reconciler has the correct values for my state, but the components affected don't re-render. My current code is almost identical to the components, identity, and state tutorial: https://gist.github.com/stijlist/53b420fb1647070b78ee001687fb0de1#file-core-cljs-L53

bert16:05:18

The UI is a simple one - click the button on line 47, and the reconciler and dom both get updated correctly

bert16:05:02

If you click the button on line 53, though, the reconciler shows " [61353.954s] [om.next] [:parameters/by-name []] transacted '[(parameters/update {:name "Salary", :value 5, :editing? false})], #uuid "08f702ab-66a3-478d-b137-b3f488e248d5" "

bert16:05:29

But the UI remains the same - :value is still rendered as 2, and :editing? is still true

bert16:05:01

"re-render Parameter", which I've been logging as a sanity check, doesn't print either

bert16:05:29

We're in the same component and both om/transact! calls are structurally identical

dgroulx17:05:34

I’m using set-query! and IQueryParams to implement routing in an SPA. The problem is that not all of my top-level components have a query. This means that any attempt to call set-query! when transitioning to a top-level component with no query generates an error “Invalid join query”. I have fixed it by creating a dummy query and associated read for such components that just returns nil, but this seems like an ugly hack.

dgroulx17:05:07

Is there any reason that set-query! couldn't accept nil joins and leave the dealing with that up to the read methods rather than throwing an error?

ag19:05:07

guys, you helped me to understand how to do reads with :query-root and om/process-roots, now I have a similar problem yet with mutations. So for my component bar I have something like:

(defmethod mutate 'change-bar-data!
  [{:keys [state]} key {:keys [bar-data] :as props}]
  {:action #(swap! state assoc :current-bar-data bar-data)})
this mutation basically says get :bar-data of a component from the state and put it in :current-bar-data (let’s say you have a list of bars and want to render details (bar-data) of each in a view next to the list. and it works when the component used as a root, but then if it is a child of another component it doesn’t, and now I have to do something like:
(defmethod mutate 'change-bar-data!
  [{:keys [state]} key {:keys [bar-data] :as props}]
  {:action #(swap! state assoc-in [:root-data :current-bar-data] bar-data)})
but what if next time I want same component be a child to another component?

ag19:05:15

oh, gosh I think I know the answer, I have to do mutations with idents, since every bar has and ident

ag19:05:14

in my case, currently I’m triggering the transactions like this:

{:on-click #(update-current-bar-data reconciler `[:current-bar-data ~bar-data] %)}

(defn- update-current-bar-data [ctx data ev]
  (.preventDefault ev)
  (om/transact! ctx `[(~’change-current-bar-data! ~data)]))

(defmethod mutate 'change-bar-data!
  [{:keys [state]} key {:keys [bar-data] :as props}]
  {:action #(swap! state assoc :current-bar-data bar-data)})
I don’t think it has to be as complicated as this, I copied it from somewhere and it worked. but apparently I’m doing something very wrong

ag19:05:28

can someone tell me how should I handle details part of the list, in something like this: https://github.com/agzam/om-basic-app/blob/master/src/cljs/om_basic_app/ledger_index.cljs

rgomezcasas20:05:10

@dgroulx: You only need to add an if 😛

dgroulx20:05:53

@rgomezcasas: So I don’t really like the if in the routing component solution since it will leave the query params set to the previous frames query which could trigger needless remote requests

rgomezcasas21:05:45

I have one read fn that contains

(defmethod read :current-page-queries
  [{:keys [query parser target] :as env} _ _]
  {:value (parser env query target)})

rgomezcasas21:05:15

But with this, the remote queries are not executed, is always trying to go local

rgomezcasas21:05:23

Has anybody faced this?

anmonteiro21:05:27

@rgomezcasas: if you think about it, the recursive parsing call is returning back to your read method and not to the original parser caller

anmonteiro22:05:09

so even if you specify :remote in that call, what the original caller effectively sees is just a map with :value, which is what you return at the topmost level

rgomezcasas22:05:42

Ok…, So there is a way to be able to do remote queries by this way?

anmonteiro22:05:23

@rgomezcasas: definitely. in your topmost read you just have to check the value of the recursive parsing call

anmonteiro22:05:37

there was an example of this yesterday here

rgomezcasas22:05:03

Ok, I’m going to try!! Thnks again, @anmonteiro 🙂

rgomezcasas22:05:40

It’s working perfectly!! Now you deserve some beers and some cubata 😛