This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-11-29
Channels
- # beginners (41)
- # cider (2)
- # cljs-dev (5)
- # cljsrn (16)
- # clojure (157)
- # clojure-russia (29)
- # clojure-uk (1)
- # clojurescript (164)
- # code-reviews (7)
- # cursive (3)
- # datavis (7)
- # datomic (1)
- # emacs (16)
- # hoplon (2)
- # ldnclj (1)
- # off-topic (4)
- # om (167)
- # other-lisps (10)
- # overtone (8)
- # parinfer (1)
- # re-frame (19)
- # testing (2)
Hi, does anybody know how can I attach static methods to the components? I would like to implement getDefaultProps
but it has to be static, although defui expects to have protocol name after static keyword and I see no protocols for such thing
Came up with this solution so far:
(defui Webview
Object
(content-text [this] (or (:content-text (om/props this) "<b>Default</b>")))
(render [this] (dom/div nil (.content-text this))))
Would be happy to see an easier or more appropriate way how to set default propsbtw - it would be cool if defui
would accept optional doc string as a second parameter, like defn
and so on
I'm wondering if this is a bug or confusion.
If I modify the AutoCompleter example query it doesn't render after the send callback is called.
Before (query [_] '[(:search/results {:query ?query})])
AFTER (query [_] '[{(:search/results {:query ?query}) [:Id]}])
I think that's a reasonable query for a remote which expects a pull query.
I have a tree of components and only the last leaf have a query and need some state. Should all of it’s parents request a query as well or can it omit it?
@artemyarulin I have the same question actually. AFAIK the parent component needs to aggregate the child components queries, but I think it shouldn't have to... Wonder why we're using a UI tree instead of a UI graph, which seems more coherent with Om's core concepts
@jethroksy: Yep, exactly that
Only explanation I found is here https://github.com/awkay/om-tutorial/blob/master/src/tutorial/om_tutorial/C_Queries.cljs#L228
well, actually it’s not an explanation but statement
Maybe somebody can elaborate on this? From the same tutorial
Beginners often make the mistake:
(defui Widget
static om/IQuery
(query [this] (om/get-query OtherWidget))
...)
because they think \"this component just needs what the child needs\". If that is truly the case, then
Widget should not have a query at all (the parent should compose it into it's own query). The most common
location where this happens is at the root, where you my not want any specific data yourself.
I’m a bit confused why this is a “beginner mistake” doesn’t work and what exactly is the right way?
@tony.kay: Maybe you can explain this part?
@artemyarulin maybe he means if the components are structured like A->B->C where B is a stateless/query-less component then just using om/get-query
on A is sufficient, but I can't seem to think of a use-case... Gotta test this out when I get back
@artemyarulin: I think some of these design issues came up a few days ago - DN - "it will take a while for people to see this but many problems can just be fixed by making up links…" Some links to the discussion - May help! https://clojurians.slack.com/archives/om/p1448317871002468 https://clojurians.slack.com/archives/om/p1448317970002479 https://clojurians.slack.com/archives/om/p1448318514002494
@artemyarulin: I think I get what @tony.kay is trying to convey here. He means that if there exists 2 components that share the same data, and only the same data but have a different representation, then yes I agree, its better to give the data an ident and pass that to the two differing views. DN has made it clear in the last link that there is no need to cascade the child query through the root.
to be fair the term "tree" is technically correct, but fundamentally confusing when trying to think in graphs...
@jethroksy: I'm not 100% sure but links are still specified in component queries and those can't just hang in the air, they have to be referenced (directly or indireclty) in the root query.
Even in the Thinking With Links! example, the Item query is referenced in the root query: [{:items (om/get-query Item)}]
. And you still need to pass the returned items (with the result of your link embedded in them) down to child components.
@jannis I understand that child queries must compose to the root, but if an interstitial component between the child component and the root component does not require the data, then it should not (and does not) require an om/get-query
for the composition to be done. Would I be correct in saying that?
Right, that's been the case all along. If you have Root -> List -> [Item] as components, List often doesn't need its own query.
all in all anything specified in queries has to somehow end up in the query in the root component
that was @artemyarulin 's question
Ok. Somehow I interpreted the discussion as being more about links than about chaining queries up to the root. Nevermind
Also, I get the same problem as @olivergeorge with the Remote Synchronization Tutorial with :onKeyUp, can't type anything into the input box unless i change it to the other recommended :onInput, can anyone else confirm?
@jethroksy: Hi, works for me with Safari and Chrome - e,g if I type in “Clojure" (over two characters). With :onKeyUp that is.
@griffio: that's odd, doesn't work for me on mozilla and chrome. It's alright then!
@jethroksy: And works for me in the Fox. I don’t think onKeyUp is an actual problem - it doesn’t work for all input types like spinners etc. Also check you are running a clean alpha24 and not master? My version is here : https://github.com/griffio/om-next-tutorial all the tutorials.
@griffio: cloned your repo and it works. I'll figure the actual problem a week later, gotta head back to my army camp xD
@jethroksy: OK - good luck!
@jethroksy: @griffio Thanks a lot, I understood it finally
OK - I think that the problem in the Remote-Synchronization-Tutorial that some were seeing with auto suggest is the input value is being set to "" each time! So pressing any key will always yield “” when using :onKeyUp -> however using :onInput instead works. https://github.com/omcljs/om/wiki/Remote-Synchronization-Tutorial In this version it is "nil" as the key doesn't exist. https://github.com/omcljs/om/blob/master/src/devcards/om/devcards/autocomplete.cljs#L65 I don't think we even need the "query" passed in for this to work. (defn search-field [ac] (dom/input #js {:key "search-field" :onKeyUp (fn [e] (om/set-query! ac {:params {:query (.. e -target -value)}}))}))
@jethroksy: @artemyarulin Yes, what @jannis said about Root->List->Item is what I'm talking about. Specifically, the beginner mistake is to use another component's query as the query of a parent. E.g. (query [this] (om/get-query Child))
. If you want to make the parent stateful, then it has to have it's own query (e.g. the child query has to be in a join): (query [this] [{:child (om/get-query Child)}])
, but then all you're doing is creating work for yourself in writing a query, teasing apart props, just to pass data through a component that wasn't interested to begin with. The only reason to do that is if the parent in this example was meant to be a black-box reusable component (so that it's parent would not know about the child's query).
@dnolen: on graph loops: When I left refs in place the tests pass, but when I tried it out in my app something when awry in server interaction at normalize*
. It was late and I figured "well, as long as it is consistent, graph loops with recursive queries are probably a non-happy path of code, and as long as we do something sane it is probably ok"
Hm, I thought the whole idea is to make all the components reusable as possible == kinda black box by default
but thanks for the explanation @tony.kay, now it’s much more clear for me. Thanks again for such awesome totorial!
depends on your level of abstraction...you can do what you want. Some components will simply be parts of some larger whole, and won't stand on their own.
@tony.kay: ok, yeah I think we should separate out why it might not for your app at the moment
@artemyarulin: sometimes it's just a function
and since we don’t have any notion of schema, db.isComponent
is always implicitly false
could you re-read that...I'm feeling like there is a typo. do you mean "is not implicitly"?
yeah, I agree....I guess the prior sentence combined with that still don't compute for me
just that we weren’t going deeper than whatever the link is without more help from user
OK, so a loop of A->B->A->B->...
should end up A->B->[ident A]
. I think the way the code is currently structured we'll end up with A->B->A->[idnt B]
.
ok. me too. I just could not remember which way I've seen Datomic do it...I seem to remember being surprised
@dnolen: one more thing...on tracking the loops. What are your thoughts on tracking the path with a set vs the map method I'm currently doing?
The set would track the two recursive queries as being the same...but I think perhaps the alg recursion might take care of that.
the two paths would be different recursive evaluations, with different tracking sets...well, unless you asked for all of the mates of all of your friends.
Is it possible to query into a matrix? for example, if I have a matrix like this...
[[1 2]
[3 4]]
Can I make a component for each cell, which updates only when it's cell changes?
So, e.g., only the '2' -> '22' causes that cell's component to update if the matrix changes to this...
[[1 22]
[3 4]]
@boz it’s possible but you will need spend some time with Om Next before it will be obvious how to make that work
@tmtwd: data
opts
is Om Now stuff. If you’re starting with Om I recommend just jumping into Om Next.
@boz not reallly, I can’t recommend anything other than going through all of the tutorials
Does anyone have any examples of the "state delta" from the merge!
doctring? I’m experimenting with remote transactions and I’m having difficulty trying to figure out what the default behavior is supposed to be.
is this a bug? when i add a :current-user
mutation to the Thinking with Links! example, the change is only rendered in one of the items. code: https://gist.github.com/sander/97c50192c24d686a1e3d
the only way that re-renders happen is if you specify the keys that need to be re-read
@dnolen: OK. I have been through the tutorials and have something working but the whole matrix and every cell gets re-rendered as far as I can tell. So I expect I’m doing something wrong. … I’ll work on it some more and ask again when I can be more clear. Thanks again
@dnolen: still getting the same behavior when the mutate-fn returns :value {:keys [:items]}
instead of :value {:keys [:current-user]}
, should i specify a different key?
@dnolen I see, still I don't get it... the query expression is '[(change-email)]
, right? should I add something there to influence re-rendering?
it seems that re-rendering only happens in the subtree from which I query the mutation. so one solution is to query the mutation from within SomeList
and not Item
I wonder if that’s the only good solution in om.next. it seems to match what I understand of React (data down, events up in the tree)
thanks, works indeed! so if I understand it well now, om.next/transact!
takes "a query expression that includes mutation" (docs), and any other queries that I want executed; the read queries will translate to (new) props passed to the root component
due to path optimization and other things the root component may or may not be involved at all
just opened up the next.cljs
source code, the transact!
doc appears actually very clear on this
so whether you get a root re-render or something more precise - that’s in your control
I assume the re-render only happens in components (+ children) that have a query reading from the specified keys, and get changed props because of that
but I'll await the path optimization tutorial before saying more possibly false things, don't need to understand how it works right now
@dnolen: I'd be interested if my comment above modifying the autocomplete query looks like a rerender logic bug.
@olivergeorge: you query doesn't make sense refer to the grammar
Okay. Will do.
Hmm, I can't see how I would say "search wikipedia for 'David' and return url and title of each result.
I guess I expected something like datomic's pull spec limit example. '[{(limit :track/_artists 10) [:track/name]}]'
Okay thanks David I'll look more closely
@dnolen: if you have a min, I'm trying to fix what looks like a problem in normalize*, but it is a lot to comprehend. I have debug output, so I know where it is going wrong, I just want to ensure i'm not breaking something.
actually not in normalize*. Looks like the tempid remap set all of the refs to nil for some reason...
Okay, worked it out from grammar/hints. Thanks. Corrected query would be something like this
(query [_] '[({:search/results [:url :title]} {:query ?query})])
@jannis, @tony.kay so from today's earlier discussion in the channel, I'm left with one doubt: after all queries don't have to compose to the root? or do they? I might have been wrong all along..
@anmonteiro: The queries in the UI have to compose to root.
with path optimization, you can supply a mechanism whereby the whole query does not have to run run from root, but instead can run from a component with an Ident....but again, you supply the mechanism (in the form of read functions that can tolerate starting from that ident (or return nil if they cannot, in which case the query will run from root)).
so if I have, as discussed, components A->B->C, and only C needs [:foo]
, does A have to declare in its query something like [{:c-query (om/get-query C)}]
?
then if A is root, it doesn't need to declare it?
in that case, the query won't really compose to root, or will it?
right, in that case yes
that I understand
but if B is stateless and declares no queries, A must declare it. Correct?
I feel like this has been a lingering question for me; and I've seen others with the same doubt. Maybe something worth adding to the wiki FAQ. I'll probably write something on this, but that'll probably need some reviewing in the channel