# om

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

sander 01:04:37

@rafd in your defroute you use om/class->any which is named a 'development time helper' in the docs. do you think using om/app-root would be better in this case?

rafd 03:22:35

if it works then it's probably better; i'm by no means an authority

rafd 03:28:52

@sander actually, you can just pass state/reconciler directly without the class->any

rafd 03:29:03

(om/set-query! reconciler {...})

adamfrey 03:37:49

I’m trying to return tempids from my server after a mutation. When I return {:tempids …} from the :action function it ends up in the :result key like, {place/create {:keys [:places/list], :result {:tempids …, but the default om function expects the :tempids key to be one level higher in the map, not nested under :result. How can get my tempid map there when I am calculating those ids in the :action fn?

andrewboltachev 03:39:41

@adamfrey: so, do you have control on your server-side code? i.e. responses?

adamfrey 03:42:30

I do, the default om parser puts the result of the :action fn into the :result key here: I could wrap the parser I guess and pull out the :tempids value myself. I just didn’t know if I was missing a built-in way to do this

adamfrey 03:43:19

or if other people already figured this out

andrewboltachev 03:46:20

well I don't know the answer then. Might be :result is for server responses

andrewboltachev 03:47:29

although parser is in *.cljc file so probably not

cigitia 06:38:05

I’m having some trouble understanding how to use Om Next queries in a certain way:
Let’s say there’s a Parent component that can instantiate many Child components.
A Parent component needs two props, respectively called :bars and :foos, both which are maps containing maps.
Each Child component needs two props: one val from :bars and one val from :foos, respectively called :bar and :foo.
The single :foo that a Child receives is determined by an :id value inside of its single :bar.
How could I express Child’s and Parent’s queries?

nxqd 06:45:58

@cigitia: you can try like this {:bars :foos} from parent

nxqd 06:46:09

then you pass down the props to child

nxqd 06:46:38

(child {:bar (get-from-bars bars) :foo (get-from-foo)}

cigitia 06:48:23

What should IQuery’s query method return for Child, though?

cigitia 06:48:49

Neither a key called :bar nor one called :foo could be understandable to the root parser, as far as I can tell; there’s no way to implement the root parser that I can see to process those keys if you request them.

cigitia 06:49:12

The parser can only know about a map of maps called :bars and a map of maps called :foos.

cigitia 06:51:20

It can’t know what particular :foo and :bar a Child needs…unless we would be supposed to use query parameters here?

nxqd 06:55:16

hmm, I'm no omnext expert but I would try my best here. actually I'm not sure about the case you want to write query, but if you just pass props like the one I show you above, and get it from child render like so {:keys [foo bar]} (om/props this) it would be fine

nxqd 06:58:05

the other way is to specify the query on IQuery of Child and write a custom read function to return correct [:foo :bar] from foos and bars. I'm not sure about this one, others might help you with this.

cigitia 07:13:56

@nxqd: Thanks for the help. One problem is that, from what I understand, queries built from IQuery are completely separate from the rendering process; they’re statically built from each other so that—ohhhhhhhh. I think I got it.

cigitia 07:14:25

Maybe child components’ query functions can return anything they want, as long as their results are understood by the parent’s query function.

cigitia 07:16:06

And so then the parent could take its child components’ (static!) queries and return something completely different—as long as that result is in turn understood by its own parent component’s query function (or the root parser).

cigitia 07:16:08

…I think.

cigitia 07:16:21

Thanks for the help again; I’ll see if this works.

nxqd 10:19:37

@anmonteiro: I think there is bug in history cljs in your aemette template, when I click back it doesn't work.

rafd 10:24:59

@cigitia child components that require two different things should be composed of components that each describe just a single thing (even if those components are JUST the query)

danielstockton 10:25:59

can anyone point me to an example of the current best routing practices in om next?

rafd 10:28:01

@danielstockton: here's what I've done:

nxqd 10:28:06

@danielstockton: check this template

danielstockton 10:28:30

thanks both

rafd 10:28:52

my understanding is that david is waiting to see if needs to be changed to better support routing

danielstockton 10:30:20

@rafd this is also my understanding, i was asking in case there was already a best practice

rafd 10:31:33

@danielstockton: nothing definitive, various approaches still

anmonteiro 13:26:55

@nxqd: looking into it

hugobessaa 14:41:47

is there a pattern to more easily test cursor transactions on om.core?

hugobessaa 14:42:34

I have many fns that transact the state and I'm not being able to simply assert my app-state without rendering to dom and testing component output

danielstockton 14:58:03

why do you want to test cursor transactions? i'd say that's the job of om's test suite, you can concentrate on testing your application

danielstockton 14:58:50

instead of rendering to the dom, you can render to a string and assert on that (maybe?)

nano 15:36:48

@anmonteiro: Looking at your lein template wrt routing, any idea how to handle queryparams on your navigation-points that result in :send calls?

nano 15:41:21

@anmonteiro: I see :navigation-data, but it doesn't seem to connect as params to the child query anywhere.

nxqd 15:53:54

hi guys, is there any good function to test remote fetching in om next ? I have specifed {:remote true} in :value but it doesn't seem to make any request.

danielstockton 15:56:55

@nxqd Did you add a :send function on the reconciler?

nxqd 15:57:27

yes, I have the send function.

nxqd 15:57:45

actually, I made it worked before in my prototype app, but now some how it doesn't work ...

danielstockton 15:58:14

so send fn isn't called?

nxqd 15:59:04

good point, let me check

nxqd 15:59:28

thanks -_-

nxqd 15:59:42

actually it has bug in that function, I haven't imported xhrio

nxqd 16:00:24

btw, is there any good way to prevent this kind of bug. Since if I use figwheel, it only shows the error in a namespace only when I change something in that namespace.

danielstockton 16:03:19

not sure, i'd say just by separating concerns as much as possible to make it easy to track down the source of any problems

danielstockton 16:03:27

usually my errors appear in the namespace im working on

a.espolov 16:05:55

In the backend there are parser method (defmethod ' inspection mutatef-target/review)
On frontede in pareser method (defmethod mutate ' inspection-target/review) is remote truebuddi

(om/transact! this `[(inspection-target/review ~other-map)]) App send request to server, server send response not found method

What am I doing wrong?

nxqd 16:07:24

if you see there is a request to backend then your frontend does good job

nxqd 16:07:33

then the problem would be on your backend instead

a.espolov 16:08:10

yes, backend not found mutate fn

a.espolov 16:08:23

for inspection-target/review

a.espolov 16:09:00

inspection-target/review loyal notation for defmethod?

danielstockton 16:10:35

front and backend parsers deliberately share the same notation, only difference is the env you pass to backend (instead of state)

adamfrey 16:24:18

now there’s more of audience in the channel, does anyone have any thoughts on my tempid question from last night:

danielstockton 16:28:00

this is one approach

adamfrey 16:31:16

that’s helpful, thanks. Tempids are going to be used in most non-trivial apps, I think, so hopefully there will be a less clunky way to do that in the future. Maybe something in the om parser?

danielstockton 16:36:32

yes, hope we'll see some standard practices emerge as things go on

danielstockton 16:36:59

but it shouldnt be hard to refactor things later

nxqd 16:52:25

I have the code below, it's quite straightforward, but somehow it doesn't work like it should.
``` static om/IQueryParams (params [this] {:dom-com/query [:a]}) static om/IQuery (query [this] '[:navigation-point {:dom-com/props ?dom-com/query}])

;; (om/props this) {:navigation-point :landing, :dom-com/props {}} ;; should it be ;; {:navigation-point :landing, :dom-com/props [:a]} ```

anmonteiro 16:55:31

@nxqd: it shouldn't if you don't have an :a prop in your app-state

anmonteiro 16:55:46

also you need to define your parser etc.

nxqd 16:56:53

@anmonteiro: I'm working on the same thing on app.cljs in your template. I try to use set-query! to change the component query then swap page with the new query from (om/props this).

dnolen 16:57:15

@adamfrey: unlikely anything around that is going to change anytime soon, certainly not until after an initial release

dnolen 16:57:35

post-processing of the :result server-side is just to be expected for many reasons

anmonteiro 16:58:59

@nxqd: right but (om/props this) doesn't have a query

anmonteiro 16:59:09

it has the props for the query of the current component

anmonteiro 16:59:35

see the parser.cljs file

adamfrey 16:59:35

@dnolen that’s fair. It probably will seem less surprising when there are a larger body of open source examples

nxqd 17:05:07

@anmonteiro: I think I get it. Basically the dom-com/props read would pass the message down. And in the read function of a page component, I return something like this {:value query :remote true} it works as expected. And of course, we can add more things like caching to value later. is it correct ?

anmonteiro 17:05:57

@nxqd: in the read function of a page component you return whatever props that component queries for, not its query

nxqd 17:08:29

yeah it's true.

andrewboltachev 21:05:40

Hi. Would om/Ident work for recursive components? I have category tree, where each node has :db/id, :category/name and :category/_parent (i.e. children) and couple of components that operates on it. But when I deref reconciler it just returns me old data. When I'm trying to mutate it using :category/by-id it gives me "No queries exist for component path " (only for first om/transact! call)

dnolen 21:06:41

@andrewboltachev: we have devcards examples that do exactly that

dnolen 21:06:57

so possibly a bug somewhere in what you are trying

andrewboltachev 21:16:58

@dnolen: may I take look on that? These doesn't seem to be what I'm looking for:!/

dnolen 21:17:23

@andrewboltachev: everything is in the Om Next repo - go look at it

andrewboltachev 21:17:48

@dnolen: ok thanks

dnolen 21:20:13

@anmonteiro: hrm I don’t know about the approach taken for displayName

dnolen 21:20:29

@anmonteiro: far as I’m concerned we should just automatically compute this from the type name

dnolen 21:21:01

being able to customize it to something else is just useless flexibility

anmonteiro 21:29:22

@dnolen: React already falls back to the type name when you declare a component, e.g. om$devcards$core$Hello

dnolen 21:29:44

@anmonteiro: right but that’s not what users want to see

anmonteiro 21:29:47

@dnolen: what I really wanted with the patch was being able to customize it, as we could do in Om Core

dnolen 21:30:16

@anmonteiro: I thought React had something like getDisplayName support no?

dnolen 21:30:45

or where if displayName is a function it should work - I don’t recall the details

anmonteiro 21:30:49

it does, by setting the string displayName in React.createClass

dnolen 21:30:51

but I asked about this 2 years ago.

anmonteiro 21:31:02

which is something we can't do in defui

anmonteiro 21:31:16

hence the alternative I took in the patch

dnolen 21:31:24

right so the patch is just a no go

dnolen 21:31:28

not going to doing it

dnolen 21:31:48

again just not interested in customization

dnolen 21:32:11

only the repercussions for tooling

anmonteiro 21:32:28

right, but the alternative is (set! (.. Component -prototype -constructor -displayName) "myName")

anmonteiro 21:32:37

which is too verbose IMO

dnolen 21:32:39

so computing a non-munged displayName property for the user would be acceptable.

dnolen 21:32:43

but that’s about it

anmonteiro 21:39:03

@dnolen: alright, so if customizing the displayName is a definite no go, I'll switch to computing a demunged name for it?

dnolen 21:43:35

@anmonteiro: yes if you feel up for it

dnolen 21:44:20

should be simple, just drop support for displayName method and just compute from the component name.

dnolen 21:44:57

should probably include the ns name

anmonteiro 21:45:22

@dnolen: it would make for more readable names in the console etc.

anmonteiro 21:45:41

I'll take a stab at it

anmonteiro 21:57:32

@dnolen: using (ns-name *ns*) to get the namespace for the component atm. is there a better way?

dnolen 21:57:54

@anmonteiro: yes in a macro you can get get it out of &env

anmonteiro 21:58:19

hah of course!

zalky 22:00:44

So I've encountered some odd behaviour with recursive union queries, mutations, and the om parser. .My example code is very similar to @anmonteiro's explorations here,, except that I used datascript in my recursive reads, and have mutations added. In a nutshell, all the queries and reads work fine on init. However when a child of a recursive union query is mutated, the union query that the read function receives gets wrapped in a vector, whereas before it is just {...}. I can't figure out if there's some assumption i'm missing (the read functions aren't that complicated), or maybe this is unexpected behaviour.

andrewboltachev 22:02:01

I've copied recursive component example from here and now I have Uncaught RangeError: Maximum call stack size exceeded error. Strange

andrewboltachev 22:02:58

"Recursive problems" are trend LOL

anmonteiro 22:04:04

@andrewboltachev: those examples are working, I would make sure you're running the current master

anmonteiro 22:04:43

@zalky: the same, recursive union queries are not in alpha 28, you need to lein install current master

zalky 22:05:11

gotcha, will give it a go, thanks

faceyspacey 22:05:23

Does Om Next support query subscriptions like Meteor? If not, now how would you go about that?

dnolen 22:06:48

@faceyspacey: it just depends on what you mean by “support”

dnolen 22:07:10

it doesn’t get in the way of it, merge! is exposed to support stream oriented subscription

faceyspacey 22:07:48

Do queries "out the box" maintain a subscription to the query, and therefore automatically receive updates?

dnolen 22:08:12


dnolen 22:08:21

very little in Om Next is automatic

faceyspacey 22:08:24

Or is there a prescribed interface to turn it on?

dnolen 22:08:37

but it’s not challenging to write whatever you need to make it work

dnolen 22:08:42

Om Next was designed around this usecase

faceyspacey 22:08:53

That's basically what I'm asking. Excellent!

faceyspacey 22:09:22

I come from the Meteor community and in the midst of switching to CLJS

faceyspacey 22:09:44

I'd love to be able to explain to the Meteor community an easy story to get the subscriptions they are used to.

dnolen 22:10:04

right so you’ll find that Om Next is significantly less turnkey than Meteor in most respects

faceyspacey 22:10:36

..i do find the query/mutation Relay-style interface way more turnkey than what Relay offers though.

dnolen 22:11:00

mostly because everybody wants to do something a little bit different - so Om Next is more like a series of lego blocks you have to comprehend in order to put together some desired larger design

faceyspacey 22:14:15

are there any docs that show an example of setting this up? Specifically with Datomic as the data source (i.e. rather than a client-only cache).

dnolen 22:14:36

not really, still tied in alpha design work

dnolen 22:15:08

you’ll have to be a bit up for adventure and figuring things out on your own for at least another couple of months

faceyspacey 22:15:36

sounds fun. ok

dnolen 22:15:54

there may be some Datomic examples floating around - people have mentioned this topic a couple of times

anmonteiro 22:25:46

@dnolen: alright, just submitted a new PR; let me know if there are any issues with it

dnolen 22:27:06

@anmonteiro: merged thanks!

anmonteiro 22:27:35

@dnolen: cool

faceyspacey 22:32:10

cool. i plan to be an evangelist for CLJS in the Meteor community. In fact I already am: ...There's a story going on in the Meteor community you may wanna be aware of: basically the Meteor community has been in the "dark" compared to the greater NPM community for a long time, coddled by all the full stack automation Meteor offers. As Meteor is going through a major change where basically React becomes their major view layer in place of their homegrown "Blaze" (among other similar changes), the community is in the process of an awakening. For example, we don't even support ES6 modules import/export, etc. We will in about a month, but we are very late to the party. Anyway, I took a lot of time off over the past 2 months to analyze all that's going on in the functional world and generally what's driving recent trends (CLJS, Om, Cycle, Elm, Haskell, etc). And my conclusion has been that CLJS, being essentially full stack, and since Om Next is getting so many things right regarding Relay and Redux-inspired features and also since it also easily supports "subscriptions" as I guessed, is the place to be for Meteor developers that expect a full stack subscription-based reactive system. Ultimately there's never been a competing solution for full stack reactivity, and CLJS + Om Next seems perfectly positioned to be the ultimate rendition of that. ...I understand that Om Next will likely require more boilerplate (i.e. the "lego blocks" you mentioned), but ultimately that's inevitable no matter which way you slice it, given the overall direction of the JS world has been toward a level of abstraction that allows for a maximum amount of choice and interchangeability (generally thanks to the design of NPM). So anyway, that's something the Meteor community has recently had to confront as superior options (mostly pioneered by Facebook) have emerged in the greater NPM community. My goal is to essentially help the Meteor community level up. I'm going to try to find the datomic subscriptions examples. If you stumble upon them, please let me know. I think you have a great marketing opportunity here by offering "full stack reactivity" and would love to continue evangelizing it.