Fork me on GitHub
#om
<
2016-02-18
>
anmonteiro00:02:02

@tony.kay: (.forceUpdate c) doesn't work?

tony.kay00:02:39

I'm talking about figwheel hot code reload: I am calling force root render on reconciler after reloads...but nothing updates because the app state has not changed.

tony.kay00:02:52

and force render from root does not seem to do it

anmonteiro00:02:22

I understood you're talking about hot reload

tony.kay00:02:25

or are you saying I should save off the mounted root component and call (.forceUpdate on it)

tony.kay00:02:41

so, what is force-root-render supposed to do?

anmonteiro00:02:54

it calls :root-render

anmonteiro00:02:03

which gets you that behavior because sCU returns false

tony.kay00:02:14

AH...I see, .forceUpdate is a React thing?

anmonteiro00:02:22

@tony.kay: would love to hear your take on my discussion with David earlier on

anmonteiro00:02:37

wrt. "routing"

adamkowalski00:02:42

@anmonteiro: well ideally I would have access to a map such as {:mouse {:left-button-clicked false :right-button-clicked true :position [100 100]} :keyboard {:keys-pressed [‘a’ ‘b’ ‘c’]}}

tony.kay00:02:46

been busy....be glad to look though.

tony.kay00:02:54

thanks for the heads up simple_smile

adamkowalski00:02:01

then the rest of my application could no longer have to think about how that information is being generated, and would simply be able to think about it as the current state of the input devices

hueyp00:02:49

@anmonteiro: is that in todays logs?

adamkowalski00:02:08

thats why I was thinking about storing that information in the global app state and then just listen to the different events that could cause a change, and transact them as they occur

anmonteiro00:02:25

@hueyp: if only we could link to a slack message

hueyp00:02:42

I can scroll! just wondering if it was today or not 😜

anmonteiro00:02:58

12h38 for you I suppose

hueyp00:02:01

:thumbsup:

adamkowalski00:02:10

with core async I would need to listen to events and then put them on a channel, then every time I pull an item out of the channel I would transact it anyway right?

anmonteiro00:02:52

@adamkowalski: yes, but it's a more sane approach IMO

adamkowalski00:02:46

ok, so maybe I am trying to do the wrong thing here

adamkowalski00:02:12

how are most om next projects handling such event streams in an idiomatic way?

adamkowalski00:02:12

I might just be trying to force a event model i am used to onto a platform that has a different approach to the same problem, and thats why things are a little hairy

cjmurphy00:02:10

What is 'sCU'?

anmonteiro00:02:23

shouldComponentUpdate

tony.kay00:02:59

hm....getting it to actually rerender deeply is problematic....forceUpdate only gets root. I can change the react key on the root every time, and that gets it, but I'm having trouble seeing where to hack in my own key for figwheel so I'm not leaving a silly thing in Root component production code,

tony.kay00:02:49

but the built-in factory stomps on all of my attempts.

tony.kay01:02:23

Got it! It was a lot easier than I was thinking...no hack needed: Put a query in root component for :react-key, embed that as :key on the root dom element, then your refresh function need only change the react-key. Bingo...rerender all

seanirby01:02:27

Ive got a normalized database with todos and todos/by-priority. When I remove a todo I'd rather not have to update both. Can I do this better? https://github.com/seanirby/om-tutorials/blob/master/src/om_tutorial/core.cljs#L37-L49

jlongster01:02:04

@dnolen: eek, I think my PR broke something. I render a tabbed interface, and tab1 uses set-query! to change query params, if I click on another tab (which uses set-state! to just change the UI), the original tab seems to get the props before my set-query! call. I suspect it's this line: https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L1622 Should I not use (props c) if I don't re-query? I'll keep looking into it...

jlongster01:02:50

(about to get off the computer for a while, just thought I'd leave that here.)

jlongster01:02:20

all the tests passed btw, I got them to run. I'll make sure to write a new test that tests whatever this broke

jlongster02:02:09

oh, shoot I think I know what's happening. The parent component of the tab1, the tab manager, still has the old result before the query params changed. Now that we don't re-run queries, it's getting re-rendered with the old props and passing them down. If we re-query we'd get the new params

jlongster02:02:47

we might have to re-query because we don't know if any query params changed in child queries

jlongster02:02:34

headed out, talk to you all later

jimmy03:02:53

hi guys what does :value :keys actually do in mutation function ?

hueyp03:02:52

I think its just purely informative / documentation

jimmy03:02:13

I feel like it's a perfect fit of how to define what kind of information we return from a mutation

hueyp03:02:37

yup, thats the information simple_smile

jimmy03:02:31

ah ha. but does it actually does return the results like I think it should ?

cjmurphy03:02:57

Can we pin this somehow? Gets asked and answered over and over!

cjmurphy03:02:40

I just pinned it!

hueyp03:02:46

I’m famous

jimmy03:02:22

haha, yeah of course I think we should. I have read it once, but it does seem a bit confused for it to behave that way. Just thought if it updates to work properly yet. @hueyp: haha 😄

marianoguerra08:02:26

maybe it's a candidate for the Om next FAQ?

geraldodev10:02:51

@jlongster: I'm pretty sure it did simple_smile My pagination suddenly stopped to work. I've suspected that code, because its related to setquery. and the pagination was working at Add invariant to build-index*. After updating om at home, I've noticed that the server was receiving the right reads, the root node read was being invoked and the nested query params was being updated but sometimes even after the nested query changes, the lines are not shown.

danielstockton10:02:39

seems like you do need to do that, unless you leave the ident and garbage collect it somehow at a later stage

seanirby11:02:10

danielstockton: Cool, thats what I figured. I don't mind it, but I suspect other users will want those updates to happen automatically. Anyways, thanks for the response simple_smile

danielstockton11:02:56

i get around it by using datascript

danielstockton11:02:31

but that means other tricky areas, like migrating tempids

seanirby11:02:50

danielstockton: yea, I mean to try out datascript at some point. as soon as I finish grokking om...

marianoguerra13:02:09

@anmonteiro: hi! just read your blog post on changes to om.next code for full hot reload experience

marianoguerra13:02:24

does it apply if I'm using figwheel? or was it more thought for something like devcards?

anmonteiro13:02:51

@marianoguerra: depends on which one you read

anmonteiro13:02:34

so that one is meant to be used with Figwheel

anmonteiro13:02:57

this one builds on Devcards to create more Om-Nexty easy-to-use cards: http://anmonteiro.com/2016/02/om-next-meets-devcards-the-full-reloadable-experience/

dnolen13:02:37

@jlongster: right stuff like that was probably the reason it worked the way that it did

dnolen13:02:20

@jlongster: there are also two kinds of tests, stuff that doesn’t really require a UI that you ran

dnolen13:02:35

and the devcards which need visual verification and interaction

anmonteiro13:02:45

@dnolen: I'd love to hear your take on this (regarding our conversation from yesterday): Say I have a dashboard like the one in the Union tutorial. In a perfect world 1) what should be the view that the root component has when we change e.g. a Post's query (e.g. from [:id :title :content] to [:id :title]) 2) what should happen to the other Post instances? should they maintain the same query or should their query change as well? 2.1) or even: should we allow both to happen

dnolen13:02:23

@anmonteiro: I think we need to go a bit deeper before we can ever start talking about 1) or 2) or some combination

dnolen13:02:44

first there’s the current assumption around set-query! where components get to change their own query

dnolen13:02:23

this actually limits options - and we should think about what happens if we put it on the chopping block

dnolen13:02:40

that is, what we if change that fundamental assumption?

dnolen13:02:13

currently set-query! really prevents parents from knowing about changed child queries

anmonteiro13:02:21

@dnolen: I understood. Requires thinking, but would make things simpler, from a 30k ft perspective

anmonteiro13:02:28

OK I agree that's the first question that needs to be asked

anmonteiro13:02:14

follow-up to that are: - what are things that currently work that would stop working in such a scenario? - would we lose flexibility?

dnolen13:02:39

we need to put some bounds on flexibility based on apps that most people will actually write

dnolen13:02:49

I’m not really interested in making anything work

dnolen13:02:03

i.e. the Union item changing it’s query in a dashboard seems … gratuitous

dnolen13:02:11

but a subview in a tab seems natural

dnolen13:02:25

tabs are bounded, dashboard views often aren't

anmonteiro13:02:54

by tabs you mean the union item, by dashboard view, the subview?

dnolen13:02:24

I mean that subquery solves the bounded subview query change problem

dnolen13:02:40

you have some bounded set of subviews, just write subquery for that

dnolen13:02:05

however for unbounded lists of heterogenous stuff - is a child changing a subquery really a reasonable thing?

dnolen13:02:11

I’m starting to think not

anmonteiro13:02:42

I don't get what you mean by bounded/unbounded. Language problem

dnolen13:02:26

Tabview with 4 possible subtabs

dnolen13:02:46

you writing your app - you know you’ll never have more than 4 or a couple more

dnolen13:02:56

you can just hardcode this and it’s really not a big deal

anmonteiro13:02:04

that's the bounded thing, I suppose?

dnolen13:02:06

subquery works fine for this case

dnolen13:02:40

but a you have a dashboard of N items (you don’t know how many there are, you’re just asking for the first 50)

dnolen13:02:46

you can’t possibly use subquery for this

dnolen13:02:36

so I think where people encounter problems is

dnolen13:02:07

“I don’t know what or how much I’m going to show” and there’s no way to express changing the query of one of these things

dnolen13:02:24

the parent can’t have it because you can’t express it at that level

dnolen13:02:37

so the child changes something, and now the world is out of sync

anmonteiro13:02:36

that brings us to what I meant by the Dashboard question I started the conversation with

dnolen13:02:33

right but I’m trying to separate things a bit more with respect to that question

dnolen13:02:46

no I do not think that case is worth solving

dnolen13:02:06

you have a list of N things - and you change the query of one thing in that list of things

dnolen13:02:34

this just seems gratuitous - I can’t see any solution that doesn’t require undesirable complications

anmonteiro13:02:54

Right, I understand that

dnolen13:02:28

however it’s different from wanting to fix this for natural tree relationships in a UI

dnolen13:02:40

sidebar, tabview, sub tabviews etc.

anmonteiro13:02:54

but it should be possible to change all the Posts queries, in my scenario

dnolen13:02:10

@anmonteiro: yes you should be able to do that

anmonteiro13:02:12

and have the root be in sync

anmonteiro13:02:26

which is not currently possible, if I understand correctly

dnolen13:02:31

@anmonteiro: which does get me thinking - based on what you were saying yesterday

dnolen13:02:41

switching from a class to the instance for the query in the indexer

dnolen13:02:54

that does seems promising to me and more so now

anmonteiro13:02:58

now I'm gettting that this is what I wanted to ask all along, I just formulated my first question incorrectly

dnolen13:02:29

so there’s a cool trick here we can leverage

dnolen13:02:03

every component has a class-path that identifies it’s location in the tree

dnolen13:02:17

for any component that isn’t in a join we can definitely just swap in the instance

dnolen13:02:39

might be enough I think

anmonteiro13:02:10

without changing anything else?

dnolen13:02:31

I think so, but not having written the code … hard to say simple_smile

dnolen13:02:49

but yeah I think so

dnolen13:02:00

every place in the indexer where we use a static class we instead switch to the instance (when it mounts)

anmonteiro13:02:30

Trying to fully understand these last bits

anmonteiro13:02:56

1. When are components not in a join? I can only think of the root

anmonteiro13:02:31

and maybe the union item

dnolen13:02:50

using one-to-many joins for organizing the UI tree isn’t a common thing is it?

anmonteiro13:02:54

No I don't believe so, what I'm getting at is how do you detect when looking at a join that there is only 1 instance or many? Maybe I'm missing something really simple here

dnolen13:02:12

hrm no it is tricky, you would have to check to see that the result of the join is a vector

dnolen13:02:26

I would set this problem to the side for now though

dnolen13:02:57

the first pass could probably be written without handling this or punting it

dnolen14:02:44

if two things mount with the same class-path you will know

anmonteiro14:02:21

the first pass at?

dnolen14:02:29

trying to make this work at all simple_smile

anmonteiro14:02:58

there's maybe one thing that we could use

anmonteiro14:02:43

we have a set of all the mounted instances in :class->components

anmonteiro14:02:59

that could probably be used to know if a join has 1 vs many instances

anmonteiro14:02:16

can't know without trying

dnolen14:02:51

@anmonteiro: btw, this is definitely a good conversation - I haven’t had time to think about the “routing” problem and I think this is the most promising idea / direction so far.

anmonteiro14:02:27

I'm happy to pick your brain, and I believe this is a good thing to be thinking about

dnolen14:02:54

yeah I think the idea is solid

anmonteiro14:02:02

I prototyped a very simple version of a query manager last night

dnolen14:02:12

I would summarize the idea as "transitioning the indexer from the static tree to the runtime tree"

anmonteiro14:02:29

but I'm not sure if the assumptions I built it on were the correct ones, after today's conversation

dnolen14:02:47

heh, I know the feeling - maybe this can obviate the need for it?

dnolen14:02:58

or make it simpler?

anmonteiro14:02:08

I'll share what it's doing anyway

anmonteiro14:02:24

at componentDidMount I index the instance query template at the data path of the parent

anmonteiro14:02:05

whenever a child changes its query, I propagate that change at the template of each parent

anmonteiro14:02:24

until reaching the root.

anmonteiro14:02:46

For very simple cases, getting the root's query was giving me a view of the changed children

dnolen14:02:05

@anmonteiro: that’s also an interesting idea

anmonteiro14:02:39

@dnolen: I'll pursue both in parallel

anmonteiro14:02:06

but the indexer stuff, if it works, should probably prove simplest

dnolen14:02:31

@anmonteiro: cool! exciting stuff

anmonteiro14:02:41

definitely agreed

anmonteiro14:02:07

@dnolen: btw, we're not validating componentDidMount's function signature

anmonteiro14:02:47

I'll send a PR your way in a sec that takes care of it

marianoguerra14:02:07

I finished writing the todo app using clojure+sql and om.next, before I write a post explaining the code I would like some feedback on the code, particularly the om related code

marianoguerra14:02:25

if someone want's to take a look, the backend om specific part is here: https://github.com/marianoguerra-atik/tudu-v1/blob/master/src/tudu/api.clj

geraldodev14:02:20

@marianoguerra: shouldn't you use {:value something} as results from the mutate and read functions at the server ? I mean, if you are using the parser at the server the same rules apply

marianoguerra14:02:50

@geraldodev: I think I have it wrong in the mutates

grzm14:02:29

@marianoguerra: thanks for sharing!

marianoguerra14:02:47

@grzm: no problem, let me know if you have any doubt or something is not clear simple_smile

marianoguerra14:02:20

is there something useful to return in a mutate? other than the tempid mappings?

marianoguerra14:02:41

(in the backend)

grzm14:02:14

@marianoguerra: I haven't dug into the code yet, but am getting an error trying to get the app up and running.

marianoguerra14:02:58

have you run "lein figwheel"?

marianoguerra15:02:33

I don't serve index.html from /

marianoguerra15:02:42

will add that to the readme

grzm15:02:24

lein figwheel works

grzm15:02:59

seeing Cannot compare <#C06DT2YSY>/id["171faee9-87f1-4175-bed4-34bcb41fbeba"] to 1 in the console when adding a new item

grzm15:02:09

Also repeated WebSocket network error: The operation couldn’t be completed. Connection refused

marianoguerra15:02:11

yes, the tempid stuff is not finished

marianoguerra15:02:33

the websocket error looks weird

marianoguerra15:02:23

I get this at page load "Firefox can't establish a connection to the server at <ws://localhost:3449/figwheel-ws/dev>." but figwheel live reload works so it seems harmless

marianoguerra15:02:28

do you get it repeteadly?

marianoguerra15:02:06

(it is because we are loading the frontend from the backend and not from the figwheel server)

marianoguerra15:02:22

if someone knows how to avoid that error let me know

grzm15:02:26

Yes, repeatedly. Am I supposed to run both the lein repl and lein figwheel?

grzm15:02:30

Looks like it

marianoguerra15:02:01

don't know a way to have figwheel and the backend repl in one repl

grzm15:02:02

well, that answers that simple_smile

marianoguerra15:02:10

don't know if it's desirable 😛

grzm15:02:40

Well, for development, likely not. Might be nice to have instructions on how to run it stand-alone/prod

grzm15:02:28

thanks simple_smile One of the benefits (?) of being a newbie is that I will likely hit every single possible bug/barrier to entry simple_smile

drcode15:02:48

Quick question: Where is the best place in an app to put calls to set-query!? Let's say someone clicks on a tab in my app, and I have a new component that becomes visible as a result, with new query requirements. Then, I could write my :onClick event look like this:

:onClick  (fn [e]
                        (om/set-query! component-with-new-child ...)
                        (om/transact! this '[...])) ;update the ui to make the clicked tab appear in the foreground
Alternatively, I could put the set-query! in the mutate action, or place it in the component-with-new-child somehow so that it can update its own query. What is the best practice for where set-query! calls should go?

dnolen16:02:47

@drcode: there isn’t a real best practice - set-query! is the thing most likely to be tweaked in the near future

marianoguerra16:02:23

let me know if you have any problem or doubt, the idea is that it's clear and useful simple_smile

geraldodev16:02:05

@drcode if what the transact does is just invoke set-query! I'm not bothering call transact! because set-query! already does, and it even allow you to read keys.

grzm16:02:03

marianoguerra: All the info is there in the documentation. For a newbie like me, I was looking for something shorter as well.

grzm16:02:22

Something like that

marianoguerra16:02:41

there's a shorter way for the backend

grzm16:02:52

Nice. Thanks! Now to look at the code 😉

grzm16:02:44

@marianoguerra: Just a couple of small editorial things I noticed.

grzm16:02:48

In api.clj, mutate -> mutatef (parallel with readf)

grzm16:02:51

In ui.cljs, it took me a bit to realize c-or-r (e.g., close-item [c-or-r]) meant component or reconciler. I think I've seen this usually just as c, and it's understood that reconciler works there as well.

grzm16:02:58

The code is pretty straightforward. I'm going to dig into your core.async stuff later to learn from it.

grzm16:02:18

It's very helpful for me to see complete examples like this. I hope my feedback has been helpful.

marianoguerra16:02:54

@grzm: the core async stuff is only for the http request, because the request returns a channel, not much magic there simple_smile

marianoguerra16:02:13

thanks for the feedback, will do the changes

doddenino17:02:51

I'm getting a Use of undeclared Var om.next/query->ast in om.next remote synchronization tutorial

hueyp20:02:19

is it legal to call om/set-state! in componentDidUpdate ? I’m not seeing it result in a render

anmonteiro20:02:42

@hueyp: I've been successful at doing that

anmonteiro20:02:57

might not work on master because of the bug introduced yesterday