This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-01-26
Channels
- # aatree (6)
- # admin-announcements (2)
- # aws (1)
- # beginners (46)
- # boot (341)
- # braid-chat (3)
- # cider (20)
- # clara (1)
- # cljs-dev (3)
- # cljsjs (7)
- # cljsrn (73)
- # clojure (63)
- # clojure-art (4)
- # clojure-dev (3)
- # clojure-russia (83)
- # clojurescript (77)
- # core-async (12)
- # core-matrix (2)
- # cursive (9)
- # data-science (1)
- # datomic (14)
- # dirac (3)
- # emacs (9)
- # hoplon (3)
- # immutant (8)
- # ldnclj (80)
- # luminus (13)
- # mount (7)
- # off-topic (4)
- # om (288)
- # onyx (20)
- # overtone (5)
- # pedestal (10)
- # perun (3)
- # proton (103)
- # quil (1)
- # re-frame (3)
- # reagent (13)
- # ring-swagger (7)
- # yada (43)
@tony.kay: Can you reference me when you complete the wiki for focus-query
. I might need the same thing for my application. Thanks
om doesn't throw, but the ast has :dispatch-key of (:from_acct {:id 1})
which seems wrong
@jlongster: not valid
;; Idea for "hideable" components:
(defui Tabs
; No IQuery presented
Object
(render [this]
(om/factory-show-if
this ; reference to parent component
'(= :route-path "news") ; this has some specific format
NewsTab)
(om/factory-show-if
this
'(= :route-path "about")
AboutTab)
)
)
It would be possible to figure out, which queries are active based on values of other queries. If framework would suppot that, then routing wouldn't need to set-query!
show-if
stolen from Angular (it has thing named ng-if
)
Do you think guys such is possible (and makes sense) to implement in Om Next?
@dnolen: I encounter a weird problem regarding read
. When a component hits the server :remote
, the data is fetched and displayed correctly. But when it's being re read from local state ( the data is already in local state ) then the props of that component is reset to nil even if I can see that there is data in read function. What could possibly go wrong here ?
;; 2nd sketch
(defui Tabs
static om/IRelativeQuery
(relative-query [_] ;; query, that depends on state itself
`[:case
(= :route-path "news"
~(om/get-query NewsTab)
)
(= :route-path "about"
~(om/get-query AboutTab)
)
]
) ; looks ugly, but it's just to show the principle
Object
(render [this]
;; ...
)
)
@andrewboltachev: how about just using simple if
and set-query!
?
@nxqd: I tried to use set-query!
, wrote a lot of code but it failed for me. I'm for sth simpler anyway
how does it fail ? because due to what I see it should work. People use set-query! to change route of the app, it should work the same way for local component
@nxqd: Hard to remember all things, it just were messy. When component were rendering it were receiving old query, for example
As for me, it seems like we need to add it one more thing: ability to "hide" components
I.e. to hide component and it's query
set-query!
is "destructive" operation, i.e. there's a reason it has bang in it's name
but declarative is always simpler
Anyway that's in my opinion, based on what idea I had just now. Thanks for your response @nxqd !
Hello everybody. I am trying to get my head around om.next. I have experience with om (om.prev). I tried om-tutorial by @tony.kay. It is really helpful. Now I am looking at the parsing.cljs from om-tutorial. https://github.com/awkay/om-tutorial/blob/master/src/main/om_tutorial/parsing.cljs. I still have not been able to understand what is going on there with db-paths. Can somebody help or share some pointers !
@tmorten: I am doing something similar with forms. I used componentWillReceiveProps
for copying the props to state. I too stumbled on the anti-pattern article and am interested in knowing whether what we are doing falls into that pattern.
@dnolen: thanks, oh, I actually meant [{:items [(:field {:arg 1})]}]
, which is a valid query I see
@tawus: Are you talking about queries? If so, check out this from @anmonteiro: http://anmonteiro.com/2016/01/om-next-query-syntax/
@tawus: I don't know if getInitState is working at this point, anyway. I get a warning and my getInitState is never called in the component
db-path is something I invented in that particular example code. It is not Om-specific. In fact, you’d be better off using db->tree
for most everything at this point, and ignore how I did it there unless you need special parsing.
@tony.kay: Speaking of db->tree, do you know how deep db->tree will go into the tree...does it have a limit?
For some reason some of my items deeply nested are showing up as empty, i.e. :persons [{}]
I recommend dumping your raw database and make sure it is all normalized as a graph using (cljs.pprint/pprint @reconciler)
Or I should say the nested items are appearing there, just not inside my component props
@tony.kay: That was my actual concern. Do I need to do all this to get things to work. (as I said I don't understand that parsing.cljs part yet) . BTW, Thanks for writing the tutorial and making things easy for newbies !
@tawus: Trying to get permission to open-source our other helpers we’re developing at work. They make it pretty dreamy. But the basic blocks are there. Our production code has a grand total of about 6-8 lines of read code…there is a little extra work you have to do around idents, but for the most part db->tree
is the work horse.
@tmorten: I’m running alpha29 off tip of master. There may have been a patch related to recursive queries in there since the last release. I wrote a bit of that recursion code, and I don’t remember where it merged…but it is pretty well tested
@tony.kay: I'll take a look at alpha29 and see if that fixes it. Thanks again for your help
@tony.kay: That would be really helpful. Are you using datomic ? I am into early stage of development of our new app (web, mobile) and we are using rest api (liberator) at the backend. Will most of the stuff/helpers apply to rest based services too ?
We’re using Datomic, yes. The helpers we have will not work as well in the particular use-case you’re describing, as we assume you’ll want to talk EDN over the wire to the server…since that makes the plumbing trivial. Technically, you can morph it on the client (via the parser or in send), but that is definitely not what we are aiming for.
@tony.kay: I encounter a weird problem regarding read
. When a component hits the server :remote
, the data is fetched and displayed correctly. But when it's being re read from local state ( the data is already in local state ) then the props of that component is reset to nil even if I can see that there is data in read function. What could possibly go wrong here ?
I am a bit spoiled by it, but I’m not necessarily suggesting you dump your entire back end…just that the abstraction of using EDN over the wire is nice. REST is a less-expressive thing, so using the EDN on the wire is nice. Once on the server, it isn’t that hard to transform it to real operations…esp for the mutations. Queries are a little harder, but not that bad…and you can always ignore the “details" of the query and send back what you “know” the client wants.
@tony.kay: can you elaborate more on the latter ? I double check the function, it does return value the through {:value }
. And since, it does display data correctly when the component mounted, this should work correctly. The problem occurs when the component is re rendered.
I would suggest printing some trace statements through your read code and see how it is being called. Om focuses queries when it does re-rendering, so your read code may be making an assumption about what it is being asked that is wrong for the re-render.
I understand. We have used liberator-om, pedestal-om and tried a few other things.Trying a datomic/ring-compojure at this stage of development shouldn't be a big problem as long as the returns are worth it. Also along with react native, it looks like something worth trying.
We’ve done a lot of work to make our stack easy and simple. Datomic was a big help when combined with Om next…actually it was the other way around, since that’s the order of our adoption.
@tony.kay: I have put the trace to print out the returned {:value
, it does print exact same thing when component first mounted and when it's re rendered.
k. me too. I’ve not had such a problem, so it is likely in your code. If you dump the tree of data (props) in your root, is the data there?
are you using om/computed to pass callbacks, or did you mess with the props directly with assoc?
That was a mis-leading question…re-render doesn’t necessarily go through root on RE-render
page 1 > page 2 ( data displayed correctly ) then I back to page 1 then to page 2 again
I remember there being a pitfall there…but I have not played with set-query! lately so I don’t remember exactly what they were.
It has something to do with the fact that the query is declared statically, yet becomes dynamically stored on the component once mounted.
but due to what I see, even if it changes, if the query is the same and read function returns same data. Then ui should displays things correctly ? but in this case component's props returns nil. I must have missed something here
If you can distill it down to a small reproducible bit of code and put it in github gists someone will probably be able to spot it, or will confirm it as a bug
no, I was going to suggest you use checkouts so that you can put debug statements in Om code for easy tracing in your code
yeah I think it should be the way. And I want to learn more about the source code as well.
Hi guys. Can anyone suggest routing approach that doesn't involve reading data for all routes at once?
I would store the active page/route in the application state. In the root component I would query for the active route, something lke :app/route
. Using the idea from, https://github.com/jdubie/om-next-router-example/blob/master/src/om_router/core.cljs, I would also construct a big map that could map route to component, however you want to only look up a single value in it--which should come from the app/route value. In order to do this, what you want to do is use componentDidMount and componentDidUpdate, and listen to changes to :app/page in the props. Using the value of :app/page, I would look up the query in the route->component map, and I would call set-query! on the root component, and add what came out of router->component to the query.
So your initial query would be
[:app/route]
After, set-query!, the query would be something like:
[:app/nav
{:app/page [{:user/home [:user-attr1 :user-attr2]}]]
@taylor.sando: Worth mentioning is that the routing example repo you mention doesn't cover child components with parametrized queries.
Are there plans on having ->Component constructor functions from defui?
@francoiswirion: not AFAIK
also not sure why you even would need that
I just thought about how to cut down on the om/factory ceremony for every Component
@francoiswirion: om/factory
is mostly about creating a React element from a React Class, but it also has some Om specifics that are need for Om to work properly under the hood
ah ok - but are there (apart from add-root!) any situations where defui wouldn't be followed by a respective om/factory call? If not, couldn't defui call om/factory itself? I was just thinking of defrecord and its automatic constructor definition side effect.
@francoiswirion: there are places where you actually need the class itself
e.g. om/class->any
anyway, assuming you always define classes with capital case and factories with lower case, the following should work:
(defmacro deffactory
[name & forms]
(let [lc-name (-> name cstr/lower-case symbol)]
`(do
(om.next/defui ~name ~@forms)
(def ~lc-name (om.next/factory ~name)))))
it can even be extended to support defui
's ^:once
metadata and factory
's options map
yes, defui would continue to generate the class itself as before of course
thanks for the macro! and thanks also for your post on reloadable code, I wasn't aware of ^:once
@francoiswirion: glad to be helping.
I just started digging into Om.now in this tutorial - https://github.com/omcljs/om/wiki/Basic-Tutorial - and I was wondering if anyone could tell me why the tutorial uses a core.async channel to handle DOM deletions, but not for additions? i.e. I am trying to understand if I’ve missed something and there is a specific reason for NOT using a channel to handle additions to the DOM?
Hi @maleghast in the tutorial it is said "Contacts don't need to be able to delete themselves, however they should be able to communicate to some entity that does have that power.” In the case of the creation, this is a classic form. Do you plan to learn Om.Now to maintain an existing App ? You do not plan to lean Om.Next ?
Any body know how to pull in a root table into a query? The entire map? Tried [:person/by-id _]
@dnolen: was going through the issues and was wondering if #436 wouldn't be something good to have soon-ish (in line with the invariant stuff, making Om more beginner-friendly)
What is the way to refer to an om.next component in another namespace ? (def comp (om/factory Comp ))
? And then how to use it ?
@nha: require the namespace and your-ns/comp
. It's just a function like all others
@dnolen: refers to "Warning if IQuery, IParams & Ident don't appear with static"
This is a bit of an oddball thought, but has anyone discussed keeping style with components, and rolling it up to the root component like a query?
I feel like I want to keep style with components in the same way I want to keep queries with components.
@peeja: you mean something like the webpack extract text plugin ?
@iwankaramazow: Possibly. That would be a static version of the idea, which is probably better. You could also render a stylesheet dynamically in response to app state changes, using a React-but-for-CSS approach, but that may not be valuable.
Alternatively, has anyone tried giving components' DOM elements automatic class names or attributes based on the component name, to make them easily selectable from CSS?
@anmonteiro: yeah happy to see someone work on that one
@dnolen: happy to do it, just checking in. I was thinking that it would be a good use of the new invariant
as well
@anmonteiro: invariant is a runtime check though, and that ticket is a macro aka compile time check
@dnolen: ah you're right, it won't work; I hadn't thought about it
should we throw
, then?
by throw I mean a JVM exception
like you have in collect-statics
hi guys, I face a problem that : I use core async to communicate events between parent and children, the problem is when I try to get states of child component, the this
seems to be outdated ( om/get-state is behind the current one 1 version ). How can we fix this ?
@peeja: no need for a separate query-like system for styles - just use queries! Using references, you can easily define "mix-ins" like in LESS/SASS and just refer to them in your component queries, alongside your data and other app state.
Hello all: has any one else been having issues where db->tree isn't going into nested items in the state? I get [{}] when try to vie from my props in component...
@tmorten: are you sure you're letting Om normalize your data? If you pass an atom to the reconciler, normalization is turned off by default, and my understanding is that in that case db->tree doesn't do anything (I.e. follow links/references)
Hmm, in that case I don't know. There are circumstances db->tree can't handle. Someone listed them here the other day, can't remember them right now. Would be nice to have in the wiki.
@hmadelaine: Thanks, that makes sense. As for Om.Now versus Om.next, I am starting with the stable one, going to see what I can get out of it, and then I will turn my attention to Om.Next. In general I tend to veer towards more stable libraries. I have limited time for investigation and learning, so I like things that I look into to nto change too much underfoot.
Hey guys, could anyone let me know how a parser remote :send callback function should present it's data? My UI is currently not displaying the fetched value and I'm not clued up enough to know how the data should be returned, nor how to debug it!
@jasonf: There are existing examples of this on the net. The Om tutorial here has a full-stack simulator (all browser side, but fully simulating interactions with a server). https://github.com/awkay/om-tutorial
If I understand your question correctly, you're asking what form the data should take when passing it to the callback in send? If so, it should look just like the return map from an Om query...e.g. query = [:a]
then callback should be called with { :a 1 }
...etc
@tmorten: is your data correctly normalized? If it is, are you passing the correct query to db->tree
, according to the piece of data you're trying to denormalize?
If your answers to my questions are both "yes", make a minimal case that demonstrates your issue
ah awesome, thanks Tony. I somehow haven't stumbled across that tutorial before. You understood my question correctly, and I've attempted to return my data in that format and it hasn't worked. The query has come from a child component however, where [:a] is relative. Does that make a difference?
I'm happy to look at it and figure it out
@anmonteiro: I am using a root query with a handful of sub-queries...so it is possible I don't have the right query setup down the line. The data is definitely there when I d'ref reconciler
@tmorten: it is important that the query is consistent with the data being denormalized...
why does db->tree
take 2 state args? sorry if this has been asked before, the API docs don't really explain it
@jlongster: it doesn’t
@jlongster: being the params [query data refs]
, the data is your real data, while the refs are the ident map, that allows you to send some deep part with the data as base and the refs aside
@jasonf make sure you wrap the data with {:value data}, just like you would with a parser on the client.
@mdhaney: I've tried the too! I think my lack of knowledge is around the root of the data. The component making the remote query isn't the root component, is one node down in the tree. From reading @tony.kay's tutorial docs, this isn't correct and I need to make it relative to the root.
@jasonf right, there is always 1 root query that gets sent to the server (same is true on the client, actually). As your app gets more complicated, it's likely you'll need to re-root some of your queries. @tony.kay has a nice description of that here https://awkay.github.io/om-tutorial/#!/om_tutorial.G_Remote_Fetch
@jasonf something that helped me was to just start simple - single remote with straightforward queries - until you understand the mechanics of everything (there are a lot of moving parts). @tony.kay tutorial is great for more real-world scenarios where you have multiple remotes, tempids, etc. to contend with, but it can be overwhelming until you understand the basics first.
@mdhaney: agreed, and I thought I was starting simple! I'm currently querying for a server's version number. I'm getting the query to the server fine, it's responding fine, but then it doesn't get displayed. I guess the complexity is that it's on a sub component of the root, which I didn't foresee as an issue. Interestingly, @tony.kay's remote docs don't make mention to {:value ...}. Is this because the tutorial code wraps that under the hood?
@jasonf I think so. I've just started really looking into his code and multiple remotes. Will probably begin refactoring towards that next week (have a demo on Monday, so can't do it until after that)
@jasonf: The remote docs are sadly unfinished...the parsing is very similar on client and server...the same parser code is used, so the return values from your read/mutates have the same requirements.
does anybody here use params on sub-keys? like [{:items [(:prop {:arg 1})]}]
? seems like params would usually be the top-level
@dnolen: David, merge-idents doesn't propagate the query, it tries to derive it from the indexer/UI. This seems like a bug...we missed this one when porting merge!
to take a query. You ok with a PR on that, or is there something I'm not thinking of?
I've got a use-case where stuff isn't getting normalized because the UI query isn't the right one to use for normalizing
@maleghast, IMHO if you have no prior knowledge about Om, you should dive into Om.Next, it will be in beta soon.
in the second part of the om.next tutorial, when incrementing Mary, I get:
=> (parser {:state st} '[(points/increment {:name "Mary"})])
{points/increment :not-found}
@tony.kay: what do you mean by "the parsing is very similar on client and server...the same parser code is used" do you actually share the same parsing code between client/server? (the same read function?)
@tony.kay: are all of datomic's API synchronous? I'm trying to figure out how to run async queries on the server but still use the parser there with a read function
@jlongster: they are not
oh, I see now that I get an error in JS console:
No protocol method IMultiFn.-add-method defined for type function: function om_next_tut$core$mutate(p__21496,key,params){
...
the object you're trying to call it on (which should be a multimethod object...made by defmulti) is borked for some reason
look at the source...defmulti just makes an object the implements a protocol, and defmethod is essentially just a call to add, which in turn just adds it to a dispatch table
(defmulti mutate om/dispatch)
(defmethod mutate 'points/increment
[{:keys [state]} _ {:keys [name]}]
{:action
(fn []
(swap! state update-in
[:person/by-name name :points]
inc))})
(defmethod mutate 'points/decrement
...
@ulsa: just copied the tutorial code and ran it successfully with current master
I'd rule out anything wrong in your environment
I meant Om master
also using CLJS 228
how would you run queries within a read function if the query API is async? here's an example, but datascript's d/q
function sync: https://github.com/awkay/om-tutorial/blob/master/src/main/om_tutorial/simulated_server.cljs#L22
@jlongster Datomic queries are synchronous. Transactions are always async (return a future). AFAIK there is no async query function built in - you'll have to build your own with futures or core.async
@anmonteiro: I get the same error with Om master
@ulsa: make sure to clean your build?
I don't use Cursive, so can't help you there
but I've seen people reporting Cursive caches builds in this channel; and that was the cause of some trouble they were having
@ulsa: we're talking about the normalization tutorial, right?
are you copying the whole tutorial code?
@ulsa: cool
@dnolen: the patch for #436 actually caught a bug in Om's devcards where an Ident
declaration didn't appear with static
. Fix also included in the patch
@anmonteiro: I don't know exactly, but it seems even if I get a prompt from figwheel, I still need to reload the browser anyway, it works now, both from terminal repl and from a cursive repl; the latter is very convenient btw
any interest in a published version of this html sugar macro? https://gist.github.com/selfsame/12c5ae9179b86760d1e0#file-demo-cljs-L15
the only thing along those lines I’m considering is server side rendering support, but that won’t be a DSL or anything
ok...the use-case I'm fixing is a little diff from the original reasoning...was just making sure it works already
agreed. The normalization is failing when I pass in a query, and it is because of the reduce.
It probably works as written...I think I just am confusing myself around the reduce...
I've got a quick question if anyone is able to help. What does: ' data in the format of an EDN result of a query expression' mean in the context a remote callback, from https://github.com/omcljs/om/wiki/Om-Next-FAQ
I feel a bit stupid here, I can't quite figure it out
got everything else working on the remote end, just can't finish off the last bit
@malcolmsparks: it just means that the data passed to the callback must be already unmarshalled
i.e. no JSON/XML etc.
and for the second part: matching a query expression that your UI understands
right - I've definitely unmarshalled it, but the data isn't appearing in my components
I must have got something muddled up in the query expressions
I'd start by checking if the data is correctly merged into the app-state
ah, good idea, thanks
if it is, make sure that your local parser can read the data once it's fetched & merged from the remote
that's really helped - I can see the state and it's not what I expect, the server data is in there, just not in the right place
@malcolmsparks: so maybe the default merge-tree
doesn't work for you and you have to override it
@anmonteiro: fixed it, thanks
the problem was that I was returning {:remote (:ast env)}
from the read
I changed it to include a :value
key
{:value v :remote (:ast env)}
then it began to work
many thanks for the tips, I was about to give up!
your blog articles have also been very useful
thanks for those too