This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-09-08
Channels
- # admin-announcements (3)
- # bangalore-clj (3)
- # beginners (21)
- # boot (32)
- # cider (14)
- # clara (2)
- # cljs-dev (19)
- # cljsjs (8)
- # cljsrn (1)
- # clojars (1)
- # clojure (147)
- # clojure-australia (6)
- # clojure-brasil (8)
- # clojure-canada (2)
- # clojure-gamedev (3)
- # clojure-greece (2)
- # clojure-hk (5)
- # clojure-italy (10)
- # clojure-japan (8)
- # clojure-korea (4)
- # clojure-russia (25)
- # clojure-sg (2)
- # clojure-spec (36)
- # clojure-uk (34)
- # clojurescript (88)
- # cursive (157)
- # datomic (6)
- # devcards (1)
- # dirac (1)
- # editors-rus (3)
- # events (2)
- # funcool (1)
- # hoplon (57)
- # jobs (9)
- # lein-figwheel (2)
- # luminus (1)
- # om (156)
- # onyx (93)
- # perun (11)
- # rdf (65)
- # re-frame (36)
- # reagent (17)
- # ring-swagger (3)
- # specter (19)
- # untangled (33)
on om (1.0.0-alpha44) and getting Uncaught Error: Can't pop empty vector
when transacting the reconciler w/ re-read idents used by components with recursive queries : https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L280
per earlier discussion, is this from not finding an IQuery path to root? (possible I have messed up my data-paths in props, defui tree has IQuery from root)
root query is [{:views {:outliner {[:roots _] [:uid {:nodes ...}]}}}]
, error happens before recur at {:om-path [:views 3 :roots 0 :nodes 1]}
@selfsame if you could provide a minimal repro and possibly open an issue so that it doesn’t get forgotten
happy to look at it when I have some time
I'm a little confused about union queries. Is it up to the implementer to decide what they mean? For instance, in the Queries With Unions example, the union query switches on the :type
of each item in :dashboard/items
. Is :type
entirely made up for the purposes of the tutorial? https://github.com/omcljs/om/wiki/Queries-With-Unions
And is it therefore meant to be well-known as part of this particular app's data model?
(It's often unclear to me when Om expects me to give something meaning, and when in giving something meaning I'm abusing a feature of Om.)
For instance, in Compassus, the root component's query includes ::route
and a union query on ::route-data
which contains queries of every component in the routing map. That works because the Compassus parser knows what that union query means: it only uses the entry from the union query that matches the current value of ::route
.
That is, which branch of the union is used depends on the value of a different key. That feels like a completely different use of union queries to me. Is it just as valid?
it dispatches on the first key of the idents, expecting a vec like [[:foo 1][:bar 2]]
, those don't have to have to point at anything technically, but usually there is data backing up the semantic
The wiki example uses unions for a mixed collection, but they let you route at the top level via a simple transact
@selfsame Ah, interesting. Are you familiar with Compassus? Does this break that semantic and abuse unions, or does this still fit? https://github.com/compassus/compassus/blob/c30481e7f1061182429f0b68c2bb46148ba745d2/src/main/compassus/core.cljc#L32
route->query
here is a map of each keyword that identifies a route to the query of the component which render that route. The value of ::route
is whichever of those keywords is the current route. The parser's read
only returns a value for ::route-data
that matches the query in route->query
that matches the current route keyword. https://github.com/compassus/compassus/blob/c30481e7f1061182429f0b68c2bb46148ba745d2/src/main/compassus/core.cljc#L143-L147
I'm not sure I follow. It's exactly that, but it should still follow the intended semantics for queries, shouldn't it?
Ah, yes, so this is getting at something I keep failing to understand about Compassus and other routing examples. There's usually a key in the app state for each page, and that key contains that page's data.
For instance: https://anmonteiro.com/2016/02/routing-in-om-next-a-catalog-of-approaches/
@peeja right but dispatching on a specific key doesn’t mean you need to have it in the app state
(at least in compassus)
nothing is stopping you from (get state :foo)
in the parser read for :index
as long as the semantics are consistent
Well, that's what I'm pushing on, then. Is it an abuse of the union construct in queries to do that? Or are unions supposed to be able to do things like that?
@peeja I don’t think there are very well-defined “Dos & Don’ts” or best practices at this point
I'm trying to figure out the "Om Next way" of doing things, and there often isn't one 🙂
unions open up a lot of design possibilities that don't depend on readers set-query, or params
@anmonteiro Incidentally, what made you choose the union query strategy over the subquery
strategy for Compassus?
@peeja well mostly driven by the fact that subquery
is normally OK for the bounded case but I wanted to support an indefinite number of routes not known before the fact
(also don’t really want to be dealing with React refs)
Couldn't you build a subquery
version out of the same route map that Compassus currently uses?
probably, but could potentially mean additional complexity
Also, as I understand it, subquery
will compose the page component's query to the root even if it's updated with set-query!
, while the union query version is always based on the page's initial query. Is that not a problem?
I tried searching through the channel and didn't see anything. Is a child allowed to delete itself through an om/transact, or am I thinking about this the wrong way. I'm trying to write a todo app with datascript and can't figure out what query I should give to the mutate.
@mjhamrick That should be fine, something like (item/delete {:id 6})
Is there a better way to change the responsibility? Right now I have at item component that has a delete button on it. When it's pressed, it sends an om transaction to delete the item from the database. Is there a way to force a re render?
The old-Om way to do that would be to have the parent transact on its cursor, and I think shifting the responsibility to the parent makes sense here too. You can do that the same way: by passing the child a function to call to delete the item.
You'll want to pass in that function as a computed prop: https://github.com/omcljs/om/wiki/Documentation-(om.next)#computed
Waaaaaaaait a minute. If I get-query
a component, do I see the latest subqueries from subcomponents automatically, merged in by their path
s?
That is, if I set-query!
a subcomponent, does that change the result of its parent's get-query
?
I thought it would only do that if I defined the parent's query
in terms of subquery
, but it appears to be doing it even without that.
@peeja: it does that if you query the instance, not the class
That was the point of my dynamic queries patch a while back :-)
I've been trying to understand how you're supposed to make everything compose to the root dynamically without subquery
everywhere. But this makes sense now: it only needs to compose to the root statically, and then the dynamic query will be updated automatically.
I switched over to competed props being passed down and it's working as intended now. Thanks again, @peeja
@peeja yes that’s right
I also wonder what makes you want to set-query!
so bad
or if you’re just trying to grasp the concepts for the sake of it
@anmonteiro I'm grappling with deeper routing params (or what I would normally thing of as routing params). So, /blog-posts/2/comment/5
needs to query for the right blog post and the right comment, and when I click "Next Comment" I want to query for comment #6.
set-query!
isn't necessarily the right way to do that, I'm also trying to grasp the concept. 🙂
I normally prefer to handle top level routing via union queries and params via app-state
well maybe I’m not getting your needs exactly but I haven’t needed to change the query, that’s what I’m saying
I'm saying that I need to query for comment #5, and then after the user takes an action I need to query for comment #6 instead
I can store "currently selected comment" as a key in the state, but I'm not sure how to affect the query
right but why would you need to change the query if the comment is the same component, thus needs the same keys?
you want the same data
I mean, you want the same attributes
but for a different ID
your query doesn’t need to have the ident
that’s what I’m saying should go in the app state
you want [:db/id :comment/author :comment/content]
for every comment
you want :curent-route {:comment-id 6 }
in your app-state
not necessarily in that structure, choose whatever fits your app’s needs
Where :current-route
is a key named for the route in question, or is a single key that holds the route data regardless of the page you're on? Or do both work?
@peeja I was thinking the latter
Uncaught #error {:message "No queries exist for component path (admin.ui.root/Root admin.ui.tabunion/TabUnion admin.ui.search.core/SearchResults) or data path [[:search :tab]]",
@peeja normally it would be something more general
like {:route-params {:id 6}}
or whatever
and if your :current-route
would be :comments
, or comment/by-id
you can generate an ident from that
@jasonjckn : an invalid query, there's probably a problem with the way you compose the query fragments to the root
@iwankaramazow if I called get-query on root, that would reveal the problem?
[:ui/react-key
{:loading-bar [[:ui/loading-data _]]}
:env-vars
:login-profile
[:nav-bar :global]
{:current-tab
{:view-listing [:which-tab [:env-vars _] :listing-id],
:guest-pending-reviews [:which-tab [:env-vars _]],
:invite-user [:which-tab [:env-vars _]],
:entitlements
[:which-tab
:sso-id
:modal
:ent-details
:ent-profile
:show-add-ent-section
:all-active],
:host-pending-reviews [:which-tab [:env-vars _]],
:search
[:which-tab
:page-size
:from
:query
:metro
:es-sort-fields
:sort-ascending?
:hits
:es-type
:time-range
:time-field
:listing-status
:bkg-status],
:view-booking [:which-tab [:env-vars _] :booking-id],
:TXJ [:which-tab [:env-vars _]],
:new-collections [:which-tab [:env-vars _]],
:reports [:which-tab [:env-vars _]],
:edit-listing [:which-tab [:env-vars _] :listing-id],
:edit-profile [:which-tab [:env-vars _] :sso-id],
:create-booking [:which-tab [:env-vars _]],
:space-transfer [:which-tab [:env-vars _]]}}]
@jasonjckn not sure if I'm right, but I think the path Om maintains will be broken if you're query doesn't compose correctly. This only shows if you transact.
It's difficult to say were you query is wrong without debugging your app
you should probably remove everything from your app to produce the minimal root query which gives that error
that's kind of awkward that there's no 'ref' argument on any of the Tab's in the tab union
with 'ref' you mean ident?
when I transact! on SearchResults, the mutation handler expects 'ref' found in 'env' to have a value non nil
If you add the necessary refs, does that solve the problem?
i don't think you're suppose to implement om/Ident for the subcomponents of a union
@iwankaramazow here's the recipe I use https://github.com/untangled-web/untangled-cookbook/blob/develop/recipes/tabbed-interface/src/client/app/ui.cljs
(defui ^:once TabUnion
;; InitialAppState can only initialize one of these (it is a to-one relation). See app.core for the trick to initialize other tabs
; IMPORTANT NOTE: We're using the state of **A** specific child. This is because a union controlling component has no state
; of it's own.
static InitialAppState
(initial-state [clz params] (initial-state MainTab nil))
static om/IQuery
(query [this] {:main (om/get-query MainTab) :settings (om/get-query SettingsTab)})
And what if you implement an ident on a subcomponent of a union?
@selfsame did you find a solution?
@iwankaramazow so I put an ident on the subcomponent of the union, and so far so good
any idea if this is proper usage of om.next? because technically TabUnion 's ident evaluates to [:search :tab] and so does SearchResultsTab
I use idents on subcomp unions too, works when they get focused updates with :pathopt, but the om.next/path gets lost on the unions on the initial render, and now is causing errors in om .44
"Uncaught Error: Can't pop empty vector" happening for recursive sub union queries in om.next/get-indexed-query
@anmonteiro How would you suggest transacting the route data into the app state? compassus/set-route!
doesn't take additional data. Should I be calling that and an additional om/transact!
from my browser history implementation? Feels weird to do two transactions at once when they could be two mutations in one transaction.
@peeja are you using Compassus?
Every time I think it's not what what we need, it turns out I'm wrong about what we need. 😜
this was here a few days ago
my answer to that was
I also don’t agree that we should be doing 2 transactions, so I suggested that we open an issue in Compassus
set-route!
could eventually take an additional argument that would be e.g a mutation to run
and instead of performing 2 transactions we’d run 1 transaction with the 2 mutations
sound good?
The other way to go would be to support "route data" explicitly (but not have opinions about how it's structured or used)
So, have Compassus accept the data, use its mutation to store the data, and then have it hand the data back to your component
Oh, I guess you don't want that, because you (the app developer) want to be able to query for the data, so you want to own the key it lives under
@peeja right, unless you come up with very convincing arguments, I would not go that way