This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-12-18
Channels
- # admin-announcements (12)
- # adventofcode (2)
- # beginners (10)
- # boot (340)
- # cljs-dev (1)
- # cljsrn (30)
- # clojure (79)
- # clojure-germany (4)
- # clojure-japan (4)
- # clojure-nl (2)
- # clojure-russia (141)
- # clojurescript (125)
- # core-async (9)
- # datascript (2)
- # datavis (8)
- # datomic (9)
- # editors (5)
- # editors-rus (4)
- # hoplon (69)
- # ldnclj (63)
- # off-topic (1)
- # om (291)
- # parinfer (7)
- # portland-or (3)
- # proton (248)
- # rdf (3)
- # re-frame (14)
- # remote-jobs (4)
@tony.kay: I’m not sure the rewrite semantics are entirely correct for process-roots
. For your expected response for test-process-roots-can-promote-a-union-to-root
it seems like you are “deciding” the ambiguity of a collection verses a single map in the rewrite rules, which may make sense since a server response is always a map. That is actually ok for my uses, but want to make sure its the desired semantics.
@tony.kay: I opened a PR for process-roots
, I didn’t see the github issue you had opened until after I had it working heh.
@noonian: Great! I did post a follow-up response on the PR. Be glad to discuss the specifics.
If you promote two things to root from a union, then it seems to me that you cannot possibly make rewrite work
its true that my test doesn’t cover that case, but thinking through it I think it only will occur if the subqueries have the same keys
[{:k { :t1 [:a] :t2 [:b] }}]
should end up with a response like { :k {:a 1} }
(singleton) or {:k [{:a 1} {:b 2}] }
(to-many)
as I see it, we can either do a naive merge, make the function more complex so you can configure the merge, or document that it doesn’t work for unions with the same keys
yeah, thats what I mean. It works in the case you just posted because the queries for :t1
and :t2
do not have “overlapping” keys
I don’t think you can have a response where they aren’t singletons since its just a map. i.e. promoting a root implies its a singleton
no, I don't thnk it does...your own test query implies to-many. Perfectly fine for a union to be asking to a hetero list of items
correct, but if you promote the values of the sub-queries of that union, then it wouldn’t make sense because in the remote response the top level keys from each item would somehow have to be repeated in the servers response which is a map
promoting a union itself makes sense for the non-singleton case, but this is also not currently supported
right, but you wouldn’t have that key if you promoted the queries from the unions sub-queries
no, because they are promoted to root your response is {:a {:id 17}, :b {:name “Foo”}}
ok, so if :b
request [:id]
like :a
does, there is no way to express the non-singleton case in the servers response
possibly...I'm talking about making the API of process-roots consistent across queries...corner cases like this do not seem to be a proper case
in one case rewrite is broken (or in need of extra help). In all others it is automatic
is the broken case you are talking about when :a
and :b
request joins on the same keys with different values?
so, come at it from the two basic uses of a union: I want to switch on a singleton, where I have an ident in my app state that alters the query when I alter the ident.
I believe the semantics for the second case are not affected by my change. If you were reading single list from the server then you would have to promote the union with the key identifying that list.
in the singleton case, your app-specific desire is to preload something that is not yet in the UI query
For prefetch, there is nothing stopping you from writing a side query, sending that to the server, and manually merging it on return
I see process-roots
as just a utility function trying to solve a common problem, so imo if you document its behavior then should be good. I think we need more tests and would not be surprised if there is a usecase we aren’t considering. I’m not quite sure what you mean with prefetch, I plan on using process-roots
in my send function which may be triggered by the reconciler
I mean that only one branch of your UI can be shown at a time...you're using the union for a UI switching concern, right?
Ah, yes. And also I can even ensure that I only ever have a single branch of the union. But it would be nice if it worked in the general case.
if you want that, why use a union at all? Why not just have a bit of app state that causes your render to only render one side and just have two joins?
I’m just trying to explore the routing usecase of a union query. I would love to have some app state that determines which side to render (and which queries to use for data) but it is hacky (in my limited experience with om next) to get that working if you want to keep your app state in your app state atom and not in your component instance.
I'm kinda out of time tonight...think through it some more. I think you don't want a union, and I disagree with the general idea of promoting more than one bit of the union. The app state approach is pretty simple, and I'm never using component local state...I want it all in the atom. All that said, I'm ok with the patch, and less ok with the test...I think promoting more than one bit from a union is a hacky thing to do that should be discouraged, since it breaks rewrite, but possibly not denied, since you should understand the implications and deal with the fallout if you want to use it that way.
I think once you've chosen a branch, the semantics of process-roots as they stand work out.
so in other words, pre-filter you unions to a single branch before using with process-roots
The way I was going to write it was as follows: - Treat each branch as a join on the join key...as if it were just another join (and not a union) - If find a root, make that a root, and add the join key to rewrite for that
anyways, changing the apply concat to just pass the single branch is all that change would be
Is my understanding correct that the indexer and merge functionality are the only parts of om.next that influence or access directly the application state? ie. outside of those concerns, the implementation of the app state is arbitrary.
Well, it has to implement IAtom at least lol. I suspect there is only one person in this chat room qualified to answer that question authoritatively.
also when you change a component query dynamically
it will swap against your application state https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L637
Is there a good tutorial or writeup on how to do nested components in Om.next? Like how IQuery works and transact?
I’m getting Assert failed: transact! invoked by component [object Object] that does not implement IQuery
and want to “read the docs"
have you checked out the wikis
yeah no worries
(we all are lol [not a diss on om next but a general acknowledgement to human ignorance at large)
so basically when you transact!
om next wants to walk back up to the parent node, see if any of the parents of the transacting component want to manipulate the tx at all
@johannjohann: thanks, looking at the source helps to demystify this
right
sorry, no context,… I’m assuming it’s my responsibility to pull the right data in the queries, and pass the right data down to the nested components...
Any good/simple om next lein templates to recommend?
@kahunamoore: I haven't tried it yet, but @anmonteiro just posted this: https://github.com/anmonteiro/aemette
How can i make the query of a parent component update after set-query in a child? I have a join in the parent component with value (om/get-query Child), yet the parent component's query does not change. Do i misunderstand something?
When doing a mutate to a remote, how could I also have (a related, but different) local change before sending the data off to the remote? I tried using :action
in parser/mutate
but this results in the UI only being re-rendered for the local change, but not when the remote response arrives and gets merged (which works flawlessly when removing :action
). The weird thing is, the same, unexpected behavior occurs when I move the expression from :action
out to a dedicated, separate mutation function in the parser. How would you solve that?
(like in the examples with optimistic updates, I am using swap
on the app-state directly, which might cause the trouble... trying to use merge
now...)
It did a similar thing and it should work. I even set the same keyword, once before sending it off, and once after. It correctly re-rendered both times.
@nblumoe: are you using devcards?
:action #(swap! ...
@nblumoe: remember that your parser may be called multiple times, that's why you need to make it stateless
but I undestand that might not be your problem now
can you please paste this parsing method entirely in a snippet?
also should mention, that I am using a custom merge-tree
, as I am retrieving data from a non-Om REST endpoint.
@wilkerlucio: do you know if set-query should work on sub components?
@smeister: I didn't played with set-query
yet, I don't know
@nblumoe: are you specifying the keys you wanna re-read after transact!
?
(for once I though adding :value
did solve it, but I was not able to make it work again. guess I was wrong on that)
I meant when you call transact!
e.g. (transact! this '[(user/verify) :users/list])
Notice I have specified users/list
to be re-read
:value
in mutate is just an indication, Om doesn't use it in any way
Is the state being updated correctly after the server response?
Does your parser know how to read the data that's coming back from the server?
(When it is local, I mean)
The state is being updated, yes. Just checked that. I see the local change, as well as the server response being merged in already
@nblumoe: Can you show the code from merge-tree?
just just added that already to the gist https://gist.github.com/nblumoe/e937103389d0173f887f
I have a problem with the following setup: i have a component that functions like a state machine to handle login stuff. If it sees a marker with credentials in the app-state, it stops querying for markers and changes it's query to one asking for an auth token from the server. But the component never gets the result props, which are correctly merged into the state. Somehow the local read seems to get the old query, which still asks for markers.
Does anyone here have any advice for using a canvas element with om next? I need to understand how best to get access to the canvas when it’s first created, to draw on it. Then, in response to changes in app state, I may need to do further drawing operations.
doesn't sound om next specific glv, you can probably look for examples with plain react
@glv that is a React thing. You just need to set a ref
on the canvas element. You can use this ref
to get a direct reference to the canvas node after your component as mounted.
Ah, OK. I was trying to figure out how to get access to the underlying canvas element from the om component, and landed on refs, but clearly didn’t get deep enough. Thanks.
@glv we’re just re-using React functionality, so there’s no recommendation over existing popular patterns already at play in the React community
@dnolen how would i best go about dynamical fetching of data in sub components? I currently try to use set-query but the parent components seem to ignore the set-query of children
Yep, and I’m coming to React straight through Om, so I’m not as up on React itself as I should be.
Btw I am still struggling with the issue described above. Meanwhile I am sure, that the app-state gets updated correctly. However, if I swap anything into the state before I get the server response, no rendering gets triggered after the response gets merged in.
Any hints about what to look for, if an application state does not trigger a re-render, even though queries seem to be correct and adding corresponding "read queries" to the call to om/transact!
do not help?
why does
static om/IQuery
(query [this] …)
take this
as an argument? also why is it a function instead of components just being initialized with a query? the way to change a query is by set-query!
not by having (query [this] …)
return a different queryHas anyone used set-query in a realistic use case with nested components? I probably misunderstand something here.
but you can use it in the meantime until it gets replaced with something with the equivalent functionality
"total query" means querying over all routes - even routes that are not displayed. then defer loading the ones not visible?
@nblumoe there's a watch on your state that will schedule a rerender, maybe adding some debugging when reconcile! is ran
Here's a gist demonstrating my current approach. @tony.kay said it sounds like a bug that it doesn't work as i expect it to. https://gist.github.com/SMeister/8d5d2ce1cdbed25cd6bb
gratitude toward the bug finders
set-query! swaps against your state
which schedules a rerender and thats how it would affect the root
I really don’t recommend trying to sort out routing yourself if you’re not comfortable with Om Next
@smeister: ok but if you’re expecting the changed query to visible from above without using subquery
it won’t work
yeah like i said, i thought the routing stuff would work and went on to deferred loading, but didn't think about the subquery thing. Thanks for the answers, i'll try do it that way.
Probably a newbie question, but I’m experiencing a weir behaviour, I’m using om/transact!
and then swap!
in the mutate
fn, just like in the tutorial. But components won’t re-render on the first click, it always re-render when clicking the 2nd time
Never mind, it’s working now. Was probably because I was using (println )
inside the mutate
fn
I'm using the basic parser infrastructure of Om.next to create an async parser, my parser is only going to be called by me (not by Om directly), what I'm doing is returning channels as values and then managing to wait and read those. it works fine for reads, but when I tried now to use with mutations I got into a problem because of this assertion: https://github.com/omcljs/om/blob/master/src/main/om/next/impl/parser.cljc#L213
since I'm returning a channel Om doesn't consider it a valid value, but if Om.next didn't enforced it would work fine for me
@dnolen: any chance to remove this assertion?
but we put the :result
of the mutation into the :value
map so you can get your channel from there
ok, wrapping in a key like you said can make it work, thanks
I'm using om 1.0.0-alpha28 and ReactDOM is undefined. [cljsjs/react-dom "0.14.3-1"] is listed as a dependency,
Any ideas? The error happens when om tries to use ReactDOM to render. root-render #(js/ReactDOM.render %1 %2)
@henriqueqc: are you actually requiring om.dom
?
yep, om.dom :as dom
Ok, I'll check it more deeply
@henriqueqc: a good starting point is to follow the tutorial instructions word for word
I'll look for diferences in the generated js output.
@dnolen thanks
@henriqueqc: I don’t the generated output is going to tell you anything
@henriqueqc: I'm also using alpha28 and had something like that which I think was resolved by adding [cljsjs/react-dom-server "0.14.3-0"]
to my deps.
@thosmos: I'll try it.
@dnolen: @thosmos Ok, I figured out what was going on. If you have a dependency before om on the dependencies vector that depends on react 0.13 (before 0.14 where they added react-dom), lein will keep react at version 0.13 and use react-dom version 0.14 from om-next.
For the record, here's a discussion on how lein chooses the versions based on the ordering of the top level dependencies: https://github.com/technomancy/leiningen/issues/1337
Unfortunately the only way to see the warning that react-0.13.3-0 is being used is to run lein deps :tree
.
Hi, has anyone successfully provided an example of integrating Om Next + DataScript + DevCards?
I've been able to integrate any set of 2 of those, but not the 3 together. I'm no master in either of those, so I'm thinking of dropping DataScript out of the equation for now.
Another reason I might drop DataScript for now is I'm not sure at all how I'd be able to handle this complexity, e.g.:
1. Let's imagine a form with a first name
input field.
2. We reconcile the field's onChange
to DataScript, which... transacts each key pressed on the keyboard, in order for it to be displayed back in the field.
3. If I add a remote, I'll have a remote API call sent out after each transaction... that is, unless I could clarify the workflow to only call the remote when the form is submitted. But then...
4. ...I'd need to manage 2 state stores: a regular one to record what's in the form fields, and the DataScript store upon form submit, including remote call. So I'd end up having to deal with manual copying between them.
Maybe someone can help spot what i am doing wrong. I have a bunch of om.next Components and everything seems to be normalized correctly. I just added a new component and the data associated with it is not being normalize, let me post the code
specifically the customers table is not being normalized on line 329 https://gist.github.com/iwillig/3a74aaa66c66a2623a99#file-admin-cljs-L329
@iwillig: if something doesn’t get normalized that’s because your data does not match the query
no namespaces in the query attributes, right?
I don't think, but it seemed irregular compared to your other components.
@danieljomphe: as far as your #2 above I typically store that data in the local component state then upon submission of the form is when i’d fire my mutation of the app state
@adammiller: ok this makes sense; I assumed we should walk away from component local state but who wants to track each key press... I'll try that, thanks
yeah, some say put everything in app state and I can see that there are some benefits to that…if you do that you’d just want a mutation call that didn’t have a remote: true part to it.
> a mutation call that didn't have a remote So that on each key press, only the app state is (locally) mutated, and on valid form submit, remote is sent... ok this would make sense and this way, things would be much more symmetric. Thinking about it more, DataScript doesn't keep history, so it doesn't seem to be a big deal anyway to have it transact each key. (And if we want some kind of history, anyway, Om is already tracking app state mutations.)
@henriqueqc: in my case, when I remove the [cljsjs/react-dom-server "0.14.3-0"]
dep, then I get this error No such namespace: cljsjs.react.dom.server
even though my Om deps look like this:
[org.omcljs/om "1.0.0-alpha28"]
├── [cljsjs/react-dom "0.14.3-1"]
├── [cljsjs/react "0.14.3-0"]