Fork me on GitHub
#om
<
2016-12-21
>
ag00:12:06

what's the generic way to limit things in data based on query, e.g. if I have a query [:records [:title]], back-end returns whole thing e.g.: {:records [{:title "one" :id 1 :amount 3][:title "two" :id 2 :amount 4]}, how in read method I would limit things so it would return records only with titles?

drcode01:12:03

@ag to return only specific fields of a record in the reader: 1. Grab parser and query out of the environment in the record reader 2. Instead of returning the record as the value for the reader, return (parser (assoc env :record record) query) 3. Write additional readers for each field of the record

drcode01:12:52

Basically, the reader for the record has access to the query, but OmNext doesn't provide any "magic" for pulling the exact fields, instead you do this explicitly as described in the steps above, which will trigger recursive parsing of the children.

drcode01:12:26

BTW, it's probably a good idea to name your fields :record/title and :record/amount etc to make it easier to write the additional readers (it's probably "best practices" these days anyway to use namespaced keywords in most situations)

cjmurphy06:12:56

However does (om/component? (om/factory HomeTab)) return true? My understanding of a component is an object that can be displayed on the screen.

fenton07:12:44

This component does display on the screen...it just prints "Hello, world!!"

fenton08:12:15

Above @anmonteiro suggests to @jannis it can come from: >the result of parsing might be empty I'll post another minimal example which also still returns false for the component? function call where I believe the parsing is not empty.

cjmurphy08:12:38

MyComponent is something like from the 'factory method' in OO design patterns. om/factory is a function that takes this MyComponent factory and produces a component.

fenton08:12:50

oh, okay. it also returns false as can be seen in my REPL interaction above.

cjmurphy08:12:34

Oh right sorry I missed that.

Lambda/Sierra14:12:30

Something I'm struggling with: How do you avoid writing a fully-recursive parser?

Lambda/Sierra14:12:00

Each component's query is parsed in the context of its parent.

Lambda/Sierra14:12:27

I don't see a way to "back out" of that context, i.e. to say "This component's query should be evaluated from the root of the application state."

Lambda/Sierra14:12:40

But maybe I'm still missing something.

anmonteiro14:12:33

@stuartsierra if you want to read something in the context of the root of the app state you can use links

anmonteiro14:12:41

i.e. '[:current-user _]

anmonteiro14:12:58

^ assuming you have a normalized app state

Lambda/Sierra14:12:44

Ahh, so idents are special.

Lambda/Sierra14:12:27

My app state is normalized, but not by Om.next.

Lambda/Sierra14:12:30

Thanks @anmonteiro, that at least gives me something more to try.

Lambda/Sierra14:12:13

yes, looking at that now

anmonteiro14:12:32

they are resolved automatically when passed to om.next/db->tree

anmonteiro14:12:59

if you're rolling your own normalization you may want to make a special case for them too

danielstockton14:12:37

@anmonteiro getting a bit confused about how to trigger route changes in compassus with pushy. Using set-route! (compassus) does not update the token and using set-token! (pushy) does not trigger a route change

danielstockton14:12:01

Is there an example anywhere with this stuff working?

anmonteiro14:12:28

@danielstockton I'm not aware of any example but by the looks of it you just need to guarantee the other is called when you call one of those functions?

danielstockton14:12:47

yeah, a hook into set-route! to trigger a set-token! would be all i needed

danielstockton14:12:07

don't need a hook, i can just write my own function which does both

anmonteiro14:12:17

which is what I'm suggesting 🙂

danielstockton14:12:33

yep, sorry, typing too quickly 🙂 i'll give it a go

anmonteiro14:12:49

the examples in Compassus's README just showcase the behavior when clicking an anchor for example

danielstockton14:12:03

yeah, that works perfectly 👍

tmulvaney14:12:14

@anmonteiro I've been having fun playing with Compassus. The Oriens template was a great entry point 😀

anmonteiro14:12:36

awesome, great to hear

tmulvaney14:12:40

I was wondering about the setting params. Currently the handler is stored under :compassus.core/route key, but the params get merged into the route which was a little unexpected for me.

tmulvaney14:12:56

They get merged into the root of the app state rather

Lambda/Sierra14:12:25

What happens if a component grabs data directly out of app-state, instead of receiving that data as 'props'?

danielstockton14:12:25

@stuartsierra I suppose you'd lose the uni-directional flow of data. The app-state could change and your component wouldn't know.

anmonteiro14:12:17

@tmulvaney right, that's because Compassus manages the :compassus.core/route key for you, but it delegates the route param management to the user

anmonteiro14:12:46

you can put it under whatever key you want, and add queries for that in your components

anmonteiro15:12:07

did you expect it would be more opinionated?

danielstockton15:12:09

The tricky thing about making a wrapper for the set-token/set-route stuff is structuring things so there are no missing/circular imports. I need the history, app, reconciler to all be available and everything is quite intertwined

danielstockton15:12:07

I have this function:

(defn set-route!
  [reconciler route]
  (let [current-route (compassus/current-route reconciler)]
    (when (not= route current-route)
      (compassus/set-route! reconciler route)
      (pushy/set-token! history (bidi/path-for bidi-routes route)))))
trouble is it's missing history which is defined in the core namespace...

danielstockton15:12:28

But I can't define this function in the core namespace because then I won't be able to require it anywhere (core requiring a namespace requiring core..)

danielstockton15:12:34

ah, i may have seen a way 🙂

tmulvaney15:12:08

@anmonteiro I just didnt expect to see them merged in to the top level of the root state but having wrapped them in {:app/params my-map-of-params} I am now happy.

anmonteiro15:12:44

@tmulvaney PR welcome to make the README clearer

danielstockton15:12:34

Is there a hook for post-merge? The merge fn has to return a map with {:keys .. :next .. :tempid} and I want to trigger a route change after doing the merge, not before

danielstockton15:12:51

root component willUpdate?

danielstockton15:12:32

Use case: login -> receive token -> merge token into state -> trigger root change to wherever the user is going

danielstockton15:12:25

I can make it work in merge using a setTimeout but that's way too hacky

danielstockton15:12:14

it actually works ok with a setTimeout of 0 ms but still might be a better way?

danielstockton15:12:22

damn, i lost my a href click handling actually

anmonteiro15:12:27

@danielstockton I'm finally looking at your Compassus issue with Links

anmonteiro15:12:47

I don't think it's an issue after all

anmonteiro15:12:57

you didn't change the parser to account for the link

anmonteiro15:12:05

Link resolution only works when you use db->tree

anmonteiro15:12:20

if I change the parser in your example accordingly, then the title is displayed again

danielstockton15:12:27

Oh, I see. I thought it would work with '_, thought it might call the parser with just the key for example

danielstockton15:12:37

Didn't realise it was hooked into db->tree

peeja16:12:03

@danielstockton It would if the '[:some/key _] were at the root of the query going into the parser. The parser only calls read with the keys at the root of the query; it's up to read to decide what to do with the query that's joined at that key, if there is one. It could decide to call the parser recursively, for instance, in which case '[:some/key _] would be at the root of the query passed into the parser at some point, and it would dispatch on :some/key. Or it could choose to use db->tree, which is essentially an optimized algorithm to accomplish the same thing for the most common cases. (Or it could choose to do something more interesting, if it needed to.)

ag23:12:25

Hey guys, I have a dilemma. Let's say I need a table-view component. Does it need to have query? If you say no, then whatever needs to be rendered in the component need to be passed via props, right? But then all that stuff need to travel down the ui-tree -> table-header, table-footer, header-cols, table rows, every single cell (let's say some cells may become components as well). Is that the right way, or table-view has to have a query? Then if I have multiple tableviews on the page, how do should I handle that?