This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-12-04
Channels
- # admin-announcements (6)
- # alda (1)
- # announcements (3)
- # aws (4)
- # beginners (233)
- # boot (82)
- # cider (11)
- # cljsjs (21)
- # cljsrn (7)
- # clojure (262)
- # clojure-japan (1)
- # clojure-russia (129)
- # clojure-sg (2)
- # clojure-taiwan (2)
- # clojurecup (23)
- # clojurescript (162)
- # clojurex (3)
- # core-async (18)
- # cursive (81)
- # datavis (183)
- # datomic (23)
- # emacs (2)
- # funcool (25)
- # ldnclj (82)
- # lein-figwheel (3)
- # om (196)
- # onyx (74)
- # parinfer (7)
- # portland-or (12)
- # re-frame (60)
- # reagent (48)
- # slack-help (1)
- # yada (9)
I needed a unique react key property on a list of child elements. I used a uuid. This sent Om Next into an infinite read/render loop. Is this a bug in Om? That is, can't use uuid as the react key? Or a case of using uuid as a solution increases problem count by one.
I think its just react then, and not om, since react uses the uuid’s to know which components have which state when they are reordered. So by generating new ones each render react probably kept re-rendering and the lifecycle things kicked off om’s stuff
I'm using http://om-bootstrap.herokuapp.com/components .. the modal .. works on the example pops up and closes ... i copy the same to my clojurescript file, it shows the button but doesn't open a modal ... no errors in console or repl ... i'm at a loss at what to do next 😕
@clojuregeek: view the source and styles of the example page and note the difference with yours. think you have to add a css class to your component for it to work.
@ianchow I tried but I will look more closely, thanks
Maybe it was mentioned here already: Found a cool tutorial for om-next with backend and frontend. http://marianoguerra.org/posts/omnext-end-to-end-part-i-backend.html http://marianoguerra.org/posts/omnext-end-to-end-part-ii-frontend.html
@artemyarulin: thanks for the link, very interesting
@jgdavey, I think another way to do it is [({:post [:post/title :post/body]} {:post/id 123})] see https://clojurians.slack.com/files/anmonteiro/F0CKAH6TS/screen_shot_2015-10-06_at_18.46.05.png
@dnolen: I read somewhere that "queries must compose to the root". Does this mean that all ui components that I want to use eventually must be reachable from the root? Can I change the root query dynamically later, for example from a module that contains a component I loaded on demand after the first render?
it also solves the problem of dashboards where you have N different dashboard item types
@dnolen: what I'm trying to do is having a router that loads for each route a module compiled in advanced mode and uses a component from the module to render a page. I can't require and reference a component from those modules in the root component (except via :export), because otherwise the resulting module is empty because the component has been moved to cljs-base. I change the root query dynamically after I loaded the module, but now I think I'm running into problems with normalization. Does this even make sense?
you're talking about modules not sure if you actually mean advanced code splitting or something else
Also nothing prevent queries from being stored in atoms or something and when modules load you extend them
@dnolen: yes, I mean modules with advanced code splitting. I load those modules on demand and they contain components with queries and idents. I think my problem is that after mounting the root component the initial state has been normalized with only the ident information reachable from the root. I think I have to normalize again after loading a module and after I changed the root query.
“normalize again” with the information I have thus far just sounds like the wrong conclusion
You may be saying ... I have all the data but not all the queries so I can't normalize everything at the beginning
But then nothing is preventing you from normalizing the state when you load the new stuff. The reconciler atom is reachable.
Having some trouble setting up url routing. My root view queries for the current :session/route and handles rendering the right component for the result of that query. Now I'm trying to add the query for that component (say, HomePage), but if "all queries must compose to root", then the root view must also know the query for HomePage, and incorporate that into its query. I've tried using a special :ui/root method of my parser's :read multimethod, but I'm unsure of 1) how to directly call read for the child component's query and 2) whether that's even the right approach. Anyone have any ideas or examples I can look at?
@tomc I’m wondering a similar thing. I have a React Native application where the root component renders a screen based on the dynamic value of :screen
in the app state. Not sure about how best to compose the query of the screen component with the query of the root component. I’d also love to see some examples.
@dnolen: are you referring to the discussion you two had this morning? I wasn't sure what you meant by "declare everything and defer"
Perhaps my understanding of union queries is wrong but couldn’t using union queries for this use case potentially over-fetch a bunch of data not relevant to the current screen/route?
@scttnlsn: I've detected a weakness in our google-fu: https://github.com/jdubie/om-next-router-example/blob/master/src/om_router/core.cljs
Is anyone using db->tree
on unions? I'm trying to figure out if I have a misunderstanding or I've found a bug
@tomc @scttnlsn I posted a mod of jdubie's router that handles browser history, urls, click capture, and modifying the query for each route. https://github.com/thos37/om-next-router-example
@dnolen: Yeah, that fixed it...I had the elements of my idents backwards because of the way I was thinking about this problem.
@thosmos: that looks a lot nicer / more how om is supposed to work. i think i’ll put a pointer in my readme to your fork. to clarify your event flow is like this, right?
item clicked -> `change-route` updates browser state -> `nav-handler` update `Root` query and state
this is clean because clicking on a menu item is the same code path as browser navigation@jdubie actually I think in that example, item clicked -> pushy updates browser state -> nav-handler
... change-route
isn't used because pushy captured the link click. That function would be called if the callback that was passed through om/computed had been used via the link's onclick event. I left it in there to easily compare pushy click capture with the explicit onclick handler.
Maybe some more comments would help clarify. Also feel free to merge it into yours if you like it.
@dnolen: Are unions supposed to work on singleton joins? I'm playing with them in my tutorial query runner, and if I refer to a collection of hetero items it works, but if I drop to a single ident then it fails.
To be clear, I asking: (is (join? {:a [:x] :b [:y] :c [:z]}))
not (is (join? {:jk {:a [:x] :b [:y] :c [:z]}}))
I understand it is not allowed by the grammar. but a join on a join is, and join? mis-detects that case when looking at it.
Let me know if you need any info on process roots. We're using it and so far it is doing exactly what we expect. One thing I thought should be added, but have not had time to: If you try to promote two elements that have parameters to the root then merge joins should throw an error.
internal refactoring stuff is not something I’m much interested in until we get everything right first
turns out the bug is using next
(or possibly the group-by...still working on it), which is calling seq on the joins map and turning it into a list of kv pairs (in the recur of the join processing loop)
just updated https://github.com/jdubie/om-next-router-example thanks to @thosmos. check it out and let me know what you think.
improvements:
- get rid of hacky top level union query and use om/set-query!
- bi-directional route syncing (om state <-> browser url). this keeps parsing pure (only dealing with data) and prevents having to use browser history and other browser apis there. this allows you to change the route by clicking on urls and back button as well as in an om/transact!
call
- using pushy to manage browser history api
@tony.kay: you might want to rebase, I merged process-roots and made a few cosmetic changes
I need to switch tasks at work...I can point you at the exact problem if you want to look at db->tree; otherwise I can work on it later
@jdubie: looks pretty good. my main problem with this way of doing it is the multiple re-renders for each transition (4 renders and 2 set-params! for the menu links) There must be abetter way.
I’ve gotten routing working with pushy by having my nav-handler
, in the router-example parlance, initiate a transaction with a mutation i.e. [(app/set-page! ~match) :page]
@dnolen: on db->tree
basically during the processing of the join on a singleton bit of data: the union itself ends up as the selector, and that gets passed back recusively to db->tree as the query. So, at entry to db->tree the query is a union, which is not allowed as a top-level query, and thus it gets interpreted as a join. Not sure if we need to change the top-level if
, or do sub-processing in the join loop.
my PR has it swapping the selector for the specific one (out of the union)...but that only works for joins on an explicit ident
You also have to make a decision about whether to use onClick functions for your links/buttons or just use the href from bidi/path-for
and let the history event initiate the transaction.
@noonian: your mutation seems like the equivalent of the nav-handler
's (om/transact! this
[(route/update {:new-route ~route}) :route])))` Also, this nav-handler
is the history event. When I remove the set-params stuff, the menu and url updates, but the page content doesn't get pulled. The question then is where and how to include the new page's query if not in set-params?
Ah, yeah when I said that I didn’t realize the router example had moved away from the way it was doing it with a join
And just re-read the pages data after the transaction and in the read impl make sure to only resolve the data for the current page. I keep a link in the app state to the current page and use that for dispatching.
@dnolen: any reason why I'm not getting query
passed in the env
map when I try out the new update-query!
?
still haven't isolated the problem
@anmonteiro: not that I can see
alright, I'll dig into it and report back
most probable is I'm doing something wrong
got a lot going on...I added a bunch of new text to many places last night...was just working on unions and discovered an Om bug, so switched to that
@dnolen: so when reading a single keyword it doesn't make sense to pass in a query, is this correct?
e.g. if my query is [{:foo [:join]} :another/foo]
, when reading :another/foo
the env won't have :query
. In my point of view it is not needed (and I was doing something wrong) but is it intended?
makes total sense, thanks. especially if I think back to when it was called selector. sorry for the dumb question
Ok guys, I have an app I’m working on that is super unfinished (basically does nothing), but the client side routing stuff may be interesting to some people and it also has a server remote that I will eventually hook up to an sql db. No promises about when I’ll get around to finishing or documenting as I’ve been sick all this week but I thought I’d mention it since it pertains to some of the routing questions people are having.
https://github.com/noonian/chatom is the github and this is the core ui component that does the routing: https://github.com/noonian/chatom/blob/master/src/web/chatom/web/ui/core.cljs
Also doesn’t actually change the page yet heh, but should have that soon. I just added the routing since people were talking about it and I’m using the old style that the routing example used, with a join query.
I was reading over the Om Next "Queries with Unions” example (https://github.com/omcljs/om/wiki/Queries-With-Unions) and wondering the best way to sort vectors of idents stored in the app-state. For instance, how would you maintain order of :dashboard/items
based on the :favorites
count of each item? Is it a matter of doing a read within mutate ‘dashboard/favorite
(https://github.com/omcljs/om/blob/b9e1b7a140448fee41d130c655f9a3ae1a340c79/src/devcards/om/devcards/tutorials.cljs#L296) to get the built out :dashboard/items
list, running a (sort-by :favorites)
and then swap!
ing that back to the atom? If I sound confused, it’s because I’m a complete Clojure newbie.
@leppert: I think you would need to re-sort the dashboard items inside your swap!
function for dashboard/favorite
. You could get the list of refs, map om/db->tree
over them using the query for Dashboard
, sort them, and them map over them again to turn them back into idents and stick the result into the :dashboard/items key of state
.
@noonian: thanks, that’s helpful context. It seems a little strange to think of going through a component to get the query, though looking at the Om Next docs that seems to be the primary route. In trying to sort like this, am I perhaps abusing the system?
@noonian: strange in this context, I mean. Generally speaking the query convention makes a lot of sense to me.
@leppert: now that I think of it, you don’t need the query at all (since :favorites
is not in a nested piece of data and so wouldn’t have to follow more than the first link). You could do something like this:
(let [st @state
refs (:dashboard/items st)
items (map #(get-in st %) refs)
sorted (into [] (sort-by :favorites items))]
{:action #(swap! state assoc :dashboard/items sorted)})
I left out the logic to actually increment the favorite of the the one you are favoriting since it would add more code
and all that logic should probably go inside the function passed to swap!
to be honest.
@noonian: thanks, that makes sense. I assumed if I circumvented the parser
I’d somehow make my data access more brittle, but I suppose since I’m writing the read
functions anyhow (no magic there) it’s no more brittle than any other app-state access?
Right, you write the reads and the mutations and Om won’t make any assumptions. The structure that Om uses for normalization is kind of your contract, and it only applies for data that is requested by your UI hehe.
@dnolen: what should next-state
in componentWillUpdate
contain when there is no state change?
(e.g. only prop change)
it's getting undefined at the moment
I did
I'm happy to submit a patch, just need some info
I think this is the problem: https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L542
should we fallback to omcljs$state
if no omcljs$pendingState
is there?
alright, submitting issue and working on a patch
thanks
@anmonteiro: thank you!
@dnolen: submitted PR: https://github.com/omcljs/om/pull/518/
@anmonteiro: thanks merged