Fork me on GitHub
#om
<
2015-11-20
>
gmcramm03:11:59

Got a pretty simple question (I think). I’m obviously not understanding something. Trying to have one component that reads/mutates (a button that increments a counter, displayed in the component), then a separate component that only reads the current count. Any ideas? https://www.refheap.com/111881

noonian03:11:52

what behavior do you see that isn’t working? do you get an error?

gmcramm03:11:51

Ah sorry - the count in the read only component isn’t updating. I hit the button to increment the count, but it’s only updating in the component that’s mutating the state.

noonian03:11:01

Try putting :count in your transaction after your mutation. If that doesn’t work you may need to use idents to make sure om knows they are backed by the same data.

gmcramm03:11:54

:thumbsup: thanks I’ll give that a try

noonian03:11:26

np, good luck!

gmcramm03:11:51

That worked. Updated paste for those who are curious: https://www.refheap.com/111882.

noonian03:11:54

Ah, so using a join fixed it?

gmcramm03:11:08

I don’t think so. At least, not as I understand joins :thinking_face:. Theres definitely some odd duplication in that example that I need to clean up.

gmcramm03:11:20

Just not quite sure how yet. I need to do a bit more reading.

noonian03:11:14

Oh my bad, I misread your updated paste

tony.kay09:11:10

Well, this is becoming a lot more of a full-blown example for an overall tutorial, but I've added a bunch of stuff to this demo: https://github.com/awkay/om-remote-tutorial The README describes it pretty well. I took some time coming up with a really nice story for writing the read functions for the parser. I also had some ideas on de-complecting UI-only app state from persisted app state, even when it needs to co-exist on a component. The server side needs a lot more work, but it is capable of "fetching". Also demonstrates a recursive query (with ...). See the devcards, as I haven't added rendering to the UI for that part yet (though it is trivial...I have to sleep sometime).

tony.kay09:11:08

It also demonstrates re-rooting server queries...though I didn't document it yet.

hmadelaine09:11:29

Hey @tony.kay @jannis have you ever thought about writing together a practical guide about Om-Next on LeanPub ? I am ready to put my money and sure others will do.

jannis10:11:00

@hmadelaine: I haven't written anything about it yet but if I were to it would be free.

hmadelaine10:11:49

@jannis you wrote a lot in Slack 😉

jannis10:11:56

Yeah, but no complete guide, tutorial or anything. Props to those who do (like @dnolen, @tony.kay), it takes effort.

grounded_sage13:11:40

Foam looks interesting. Would be interesting to see the difference between that and Node on Lambda for server side rendering of om

dnolen13:11:58

@grounded_sage: I suspect anything Foam like to soundly beat anything that involves running React

dnolen13:11:10

there’s a good chance we’ll just support @arohner’s Foam concept directly

dnolen13:11:01

@grounded_sage: that said I suspect this approach will require discipline and I foresee many cases where just running React server-side is just easier

grounded_sage14:11:57

@dnolen: how will that work? Will it be just making it trivial to use like datascript? Or will it make Om more Clojure focused.

dnolen14:11:40

@grounded_sage: I don’t see why it would be any different than what @arohner’s basically suggested

dnolen14:11:48

I don’t understand your followup questions

grounded_sage14:11:44

Oh I think I get it. Just porting it to Cljc

arronmabrey14:11:48

Sorry are you all talking about this project, https://github.com/farisnasution/foam ??

arronmabrey14:11:31

(trying to follow along)

grounded_sage14:11:39

That's alright. Bit tired so questions are probably a bit hazy. Just assessing trade offs. Tempted to use Pheonix framework in Elixir land as I feel docs, more set path for developing backend apps, insane concurrency, coolness of OTP and I feel deployment will be easier due to all these. But I really do prefer Clojure as a language.

grounded_sage14:11:18

Yep that's it.

jethroksy14:11:20

got exposure to it at clojure conj

grounded_sage14:11:32

I'm on iPhone with shattered screen so a bit slow :p

dnolen14:11:03

@grounded_sage: Elixir/Pheonix look really cool, that’s for sure

jethroksy14:11:49

@anmonteiro: yup I watched it but couldn't quite gollow... would love to see an example Foam app somewhere

grounded_sage14:11:10

@dnolen: you also mentioned in your talk that with Om Next you could cache everything? Then move to Datomic at a later date. Is that right?

grounded_sage14:11:11

@dnolen: you also mentioned in your talk that with Om Next you could cache everything? Then move to Datomic at a later date. Is that right?

dnolen14:11:59

@grounded_sage: all I meant was that the HTTP caching layer is an easy way to deal with things that are challenging to optimize

dnolen14:11:31

this why slow language runtimes or slow DB queries aren’t really a problem for many web based applications

dnolen14:11:57

so Om Next supports HTTP caching out of the box

dnolen14:11:16

meaning you can probably make the model work even if your backend decisions are modest / conservative

grounded_sage14:11:30

Ah I see. I must have misinterpreted that part of the talk. Thanks for clarifying that for me :)

arronmabrey14:11:41

@dnolen: in your talk / example. You separated dynamic user likes from the rest of the feed. That way you could cache the static feed and mixin the dynamic user likes. In that example the feed must be exactly the same for every user... no? I mean if the entire feed was unique to each user e.g. instgram / fb news feed. Then you can't cache that... correct?

dnolen14:11:23

@arronmabrey: the question seems strange … can Om Next cache uncacheable things?

arronmabrey14:11:38

Well I guess in the example (I think) you used the word feed, and I guess my mind went straight to a user feed like instagram / fb. But I don't think that's the type of feed you were referring to. I think maybe an example of what you were referring to could be the public/trending twitter stream. Where it's the same for a large group of users where some of the users may or may not have liked one of the tweets in it.

arronmabrey14:11:37

I'm just trying to clarify in my mind which type of feed it was in the example, and I think I answered my own question 😉

dnolen15:11:48

@arronmabrey instagram / fb problem is really not any diffferent. different applications cache different things.

dnolen15:11:06

focusing on the app domain of my talk example would be misunderstanding my point.

dnolen15:11:11

the only thing that matters is that you can cache whatever part of the query makes sense for your application using traditional methods

arronmabrey15:11:18

@dnolen: thanks, that makes total sense.

tony.kay16:11:19

@hmadelaine: on docs: I certainly take help from anyone. I do periodically talk to @jannis and anyone else who will listen in order to get feedback and clarification...but I also have a whole team of people to train, so I'm already getting paid to write docs (because I choose to do so, because the is the most effective way to train a bunch of ppl in parallel). Putting them on the net just gives back to the community.

jamesnvc16:11:31

For the Foam talk previously, isn't it more straightforward to just server-side compile with nashorn? That's how I've done that

anmonteiro16:11:50

he mentioned in the talk that nashorn is "very unpolished"

jamesnvc16:11:55

Or am I misunderstanding what that does? It lets you generate pre-compiled html you can send down?

anmonteiro16:11:00

some things don't work

jamesnvc16:11:57

oh? Interesting

jamesnvc16:11:31

Like, some clojurescript-specific things don’t work, or some general javascript things don’t work?

dnolen16:11:49

Nashorn just has a lot of bugs, it’s a very new implementation

dnolen16:11:44

alright new thing to ponder @joshfrench’s Union issue has demonstrated a problem with om.next/IDent

jamesnvc16:11:46

but it should work for just pre-compiling static html, yeah?

dnolen16:11:00

I’m wondering if doesn’t just make to sense to om.next/IDent in-band

jamesnvc16:11:03

It is quite slow, but it’s worked sufficiently for us

dnolen16:11:34

[{:foo [:id :type :bar :baz] :om.ident [:type :id]}]

dnolen16:11:58

so all the information for computing idents is in the query itself

dnolen16:11:12

this actually really improves the “just data” story of ident calculation

dnolen16:11:27

currently the current approach suffers in having to have the types that implement om.next/IDent

dnolen16:11:37

the old approach works OK but then you hit union queries and you’re hosed

dnolen16:11:06

feel free to ruminate on what I’ve said ^ and provide feedback simple_smile

anmonteiro16:11:45

@dnolen: at first sight looks OK

anmonteiro16:11:28

seems like om/get-ident will be of great help then (since you removed it a while back - and then reinstated :P)

anmonteiro16:11:18

compromises readability a bit, maybe?

dnolen16:11:19

alternative ideas also welcome especially if you’ve poked around at om.next internals

dnolen16:11:49

another possibility is to support both om.next/Ident and the inline version and see where we end up.

dnolen16:11:24

you only really need the later if you want generic processing pipelines w/o needing any defui types to help you

chris-andrews16:11:42

I really like the above :om.ident bit you just showed

dnolen16:11:45

or if you’re dealing with union queries

chris-andrews17:11:08

It seems like that approach with the ident in the query itself means you could have several normalized keys in a single query. Not sure how useful that would be, but it could help accomplish certain things

tony.kay17:11:30

@dnolen: Hm. Well, it seems like you could still supply a get-ident that can take a component or class (by analyzing the query). I'm a little torn on the grammar itself. The way you've written the join implies the parent would specify the ident of the child? {:foo (om/get-query Foo) :om.ident [:type :id]}

tony.kay17:11:29

that seems not as nice

dnolen17:11:33

@tony.kay: you would need a way to override that’s for sure

dnolen17:11:52

I’m leaning towards just restricting this to union queries

dnolen17:11:06

there are advantages to overlying ident however you see fit at runtime

dnolen17:11:27

the way it currently works

tony.kay17:11:41

The union query story is much more limited in the UI, so the loss of transparent composition seems fine for that limited case.

tony.kay17:11:34

just throwing it out there, but we already understand query params....ident params?

tony.kay17:11:43

or ident switch/key/toggle

dnolen17:11:30

the problem here is the problem of type erasure

dnolen17:11:39

we don’t know who knows this

dnolen17:11:49

this is why it needs to be in-band for union queries

tony.kay17:11:49

oh right, in the union case. I was talking about the general case

tony.kay17:11:31

but I personally see no reason to switch up a regular component's Ident...I was getting the impression that others did

dnolen17:11:16

yeah was just thinking out loud, I think the current flexibility of om.next/Ident is a good thing

tony.kay17:11:37

Ah, and query params could be used to mess with the embedded :om.ident value...so that's nice (or at least, flexible)

dnolen17:11:57

yeah I wouldn’t take it there yet simple_smile this will only work for union for now and I would not mess w/ it via params for the time being

tony.kay17:11:42

agreed, just saying, if people found a need to vary it, it would work

tony.kay17:11:04

not saying it sounds sane to me simple_smile

tony.kay17:11:43

So, I'm about to write up something on the default database format. Hows this sound? "The default database format has the client local state stored in a tree that matches the structure of the query response, and all items with an Ident are pulled out into flat tables at the root of the state and replaced with refs".

tony.kay17:11:00

I'm basing this on my understanding (reading of tree->db). Want to clarify in docs

dnolen17:11:56

yes I would not say ref

dnolen17:11:00

I would just say ident

dnolen17:11:06

ref is Om-ish around the Indexer API

dnolen17:11:11

where the type of the thing is variable

tony.kay17:11:27

Ah. Ok. I'll define that as terminology. What are you calling a ref?

dnolen17:11:38

so this needs to be made more consistent

dnolen17:11:44

ref = (keyword|ident|component)

tony.kay17:11:12

ref like a pointer?...something you can walk to in a graph?

dnolen17:11:42

it really is only something we should use around the indexer api

tony.kay17:11:24

so, we need to rename (om/ref?)

tony.kay17:11:58

I've been using that in my parse helper functions to walk the graph...which is why I'm using the term

tony.kay17:11:30

BTW, whoever suggested doing tutorials in devcards...that is what I've decided to do, and it is working very well simple_smile

dnolen17:11:09

I didn’t even realize ref? was a thing but probably

tony.kay17:11:12

yeah, being able to write tests in there let's you just slam in arbitrary code that ppl can see running and play with

tony.kay17:11:28

line 1073...you forgot writing it ? simple_smile

dnolen17:11:34

by now yes simple_smile

tony.kay17:11:55

to your credit, it does say "TODO: revisit"

tony.kay17:11:54

and the ident? function isn't what I would expect now, since it is a "does it implement?" meaning

dnolen17:11:57

right but I don’t really believe in ref? besides an internal helper thing

dnolen17:11:11

you cannot really know whether something is or isn’t an ident without the query in hand

tony.kay17:11:21

which is what I'm using it for.

tony.kay17:11:37

I've written parsing helper functions that make it really easy to build read for the default db format

tony.kay17:11:47

but I need to auto-detect and walk the graph while I'm doing it

dnolen17:11:48

yeah my brain isn’t there yet - but if there's ideas about what needed for custom traversal, people should bring that up

dnolen17:11:55

need to fix these bugs first

tony.kay17:11:46

k. I'm off to writing

noonian18:11:36

Just throwing in my two cents, I currently use the ref? helper in my parser’s default read so that it can automatically follow references/idents.

grzm19:11:22

besides @dnolen 's om-next todomvc demo, any particular references I can use to learn more about om next query syntax and interaction with the server side? Feel free to point me to the source code as well.

grzm19:11:25

looks like awkay/om-remote-tutorial would be potentially useful

dnolen19:11:58

@grzm: there’s a few community things, nothing more official yet

grzm19:11:10

@dnolen: is there an entry point that might have a collection of links to such community things? Or particular github users/repos you'd recommend or know about?

grzm19:11:41

@dnolen lol. I was just typing that myself simple_smile

grzm19:11:02

@dnolen: specifically, you're referring to the Community Resources section at the bottom of https://github.com/omcljs/om/wiki , correct?

dnolen19:11:20

yes though they may be out of date

grzm19:11:25

understood

dnolen19:11:25

details are still changing

jannis19:11:47

@grzm: My kanban demo is a little out of date (still on normalize instead of db->tree etc.) but fairly clean; copaste is more experimental and less clean, but therefor more or less up-to-date and comes with server-side communication.

taylor.sando19:11:14

Looking at some of the om next tests can help you understand some of the code. https://github.com/omcljs/om/blob/master/src/test/om/next/tests.cljs Anything past line 160 seems relevant

taylor.sando19:11:43

Though probably not a starting point, but something to look at after you have went through the main documentation/tutorials and @tony.kay tutorials

tony.kay19:11:13

@grzm: The Om Next Overview is pretty much up-to-date...and the new tutorial should come spewing out pretty quickly.

settinghead20:11:06

is there an example on how to do routing with om.next and with libraries like bidi and secretary?

kevinmershon20:11:21

If I have two components in different parts of my app, and I want to send the results of an event on one to the other for render, what's the best practices what of doing that? A channel? Root shared state?

noonian21:11:59

If the event is a mutation from a transaction in one component, you can put keys in the transaction after the mutation specifying which keys to read after the mutation to cause a re-render

tony.kay21:11:27

Just finished recording a whiteboard session that is an overview of Om next. Might be helpful for those trying to understand how the overall system works...though you'll need to combine it with a reading of the basic tutorial and overview. https://www.youtube.com/watch?v=IlNrmKYA7Ig&amp;feature=youtu.be Youtube transcoding should be done within a minute.

grzm21:11:07

@tony.kay it was nice to talk to you the other morning at the conj at breakfast

kevinmershon21:11:35

@noonian: Thanks. I'm getting a re-render of component A (if A had a state change), but I need to fire the mutation data to component B, where A and B share a parent component. Thoughts?

noonian21:11:39

I would think if you put the keys that the parent component reads in your transaction after the mutation it would force a render for both of them

kevinmershon21:11:28

OK, I'll give that a shot

tony.kay21:11:35

The tutorial I'm working on has moved to using devcards to make a more interactive experience, and I've just pushed an update. Starting it is a little different than before. You want to clean your project before restarting it: https://github.com/awkay/om-tutorial (RENAMED)

noonian21:11:08

@kevinmershon: Ah I’m sorry, I thought you we’re using Om.next, root-cursor is from Om.now so my advice probably didn’t make much sense 😛

dnolen22:11:36

forget about all the union mumbo jumbo I said this morning 😛

dnolen22:11:50

@joshfrench: your issue is fixed and it was simple

joshfrench22:11:24

oh good! i’m so used to being the guy who finds the aggravating edge case, just ask my coworkers troll

Tim22:11:56

is there a way to query an om component for its css ?

dnolen22:11:55

@tmtwd: Om components don’t have CSS

dnolen22:11:06

React DOM components do

dnolen22:11:25

and that is a React question

dnolen22:11:47

you can get a React ref to the DOM node and inspect the CSS if you like

Tim22:11:03

using clojurescript?

dnolen22:11:18

this question is purely an interop question

dnolen22:11:54

Om components are React components so all of this documentation applies

jannis22:11:02

@tmtwd: (render [this] ... (dom/div #js {:ref "child"})), then somewhere else in the same component: (.-style (om.next/react-ref this "child") should work, basically

tony.kay22:11:06

@jdubie: I have not looked into speed testing my helpers, but I cannot see where my helpers would be slow at all. You might add in some printlns and make sure you're not accidentlly doing things you don't expect.

tony.kay22:11:02

but if you find some kind of bug or gotcha, let me know. I'll be documenting those in a day or two....lots to write

dnolen23:11:45

@jdubie: if your queries are 10 levels deep you’ll need to look into path optimization

tony.kay23:11:14

@dnolen: is pathopt done?

dnolen23:11:26

far as I know

dnolen23:11:33

I’m sure people using it will find bugs

tony.kay23:11:27

Is it a function that takes an ident and returns value, or is it a parser?

dnolen23:11:12

if you configure :pathopt true then your read fns needs to check for :om.next/root

dnolen23:11:31

this means parsing is starting somewhere other than :root

dnolen23:11:52

I mean check for :query/root

dnolen23:11:44

by default this is :om.next/root

dnolen23:11:00

but if you enable :pathopt and the component has an ident

dnolen23:11:09

:query/root will be that instead

tony.kay23:11:03

ok, so on entry to the read function, check for :query/root...what do you do if you can't support that root?

dnolen23:11:04

return nil

tony.kay23:11:17

yeah, I just read it in the source...thanks

tony.kay23:11:15

ok. You mind if I add that to the main docs (Documentation) for reconciler?

dnolen23:11:09

I’d likely somebody to actually try it first

tony.kay23:11:34

OK. I'll get to that in a couple of days. It is going in my tutorial

tony.kay23:11:44

so I will have tried it

dnolen23:11:27

@jdubie: as far as your problem you should be able to see this behavior without bothering with a UI at all

dnolen23:11:42

you can just measure the performance of parse on your app data