This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-06
Channels
- # aws-lambda (6)
- # babashka (1)
- # beginners (204)
- # calva (10)
- # chlorine-clover (17)
- # cider (57)
- # cljs-dev (3)
- # cljsrn (3)
- # clojure (148)
- # clojure-bangladesh (1)
- # clojure-berlin (3)
- # clojure-europe (30)
- # clojure-france (1)
- # clojure-italy (4)
- # clojure-nl (5)
- # clojure-spec (4)
- # clojure-uk (14)
- # clojurescript (15)
- # code-reviews (8)
- # conjure (27)
- # data-science (9)
- # datomic (38)
- # duct (6)
- # figwheel-main (11)
- # fulcro (78)
- # helix (11)
- # jobs (1)
- # malli (18)
- # meander (22)
- # mount (4)
- # nrepl (3)
- # off-topic (93)
- # pathom (2)
- # pedestal (4)
- # re-frame (5)
- # reagent (6)
- # reitit (1)
- # ring-swagger (1)
- # sci (1)
- # shadow-cljs (19)
- # spacemacs (1)
- # sql (1)
- # tools-deps (76)
- # unrepl (1)
- # vim (5)
- # xtdb (8)
Hi, if I have a component with ident [:person/id :person/id] and I want to have a dropdow with all the other persons in the db to select from. It would be nice to have a link query [:person/id '_]. How do I get the link query to coexist with the :person/id query?
@magra so technically you cannot in the query, since an ID must be at that key in the props. You could construct a list of idents as a top-level key like :dropdown/all-people
that is a list of idents to people (which could also be one of your load targets). This has the added advantage of being able to reify the sort/filter of the options.
You could look in app/current-state
within render
, but that will not refresh properly unless you also change shouldComponentUpdate
to true on that component…and even then certain renderers (like ident-optimized) might not properly figure out what to refresh.
RAD uses the first approach, but further generalizes it to use an options (picker) cache with a configurable TTL. Thus 100 different rows in a table that all want the same options for a dropdown end up sharing that centralized cache.
The second approach is viable, and just puts all the logic in render. This avoids “cache staleness” but costs a bit more in render (which may be perfectly fine)
I have query troubles with df/load!... Let's say I have a component with ident [::ExampleView :example/id]
. In will-enter I run the df/load!:
(df/load! app [:example/id id] ExampleView
{:post-mutation `dr/target-ready
:post-mutation-params {:target [::ExampleView id]}})
And it loads - but to the root key :example/id, instead of ::ExampleView. Leading to that the defsc has nothing in its propsYou put the :target in the post-mutation-params, so it gets past to dr/target-ready. You need another target to target the load.
(df/load! app [:example/id id] ExampleView
{:target [::ExampleView id]
:post-mutation `dr/target-ready
:post-mutation-params {:target [::ExampleView id]}})
Should work but perhaps the two colons :: won't resolve correctly.I want to load it into [::ExampleView id]. I thought since the query object's ident is already [::ExampleView :example/id] the :target wouldn't be necessary
Yea I tried with :target now, the only difference is that it places [:example/id #uuid "whatever-the-uuid-is"] inside ::ExampleView
I think you want to put it into [:example/id whatever] in the normalized db. That has nothing to do with the component.
I mean I can change the component ident to :example/id and it works, but that can't be the only way
I think I changed it because I had problems with having more than one form with :example/id, and them existing, even if they weren't loaded simultaneously, gave me weird behaviour
You query for it and make shure that either your query composes from root or you query with a link query like [:example/id id].
Oh I know that. Oh well, guess I'll simply change the ident then. No time to investigate, there's loads of things to finish
@zilti The :target needs to be on the same level as :post-mutation-params, not beneath it.
How does form/save-form* behave with refs of cardinality many? Is it possible to add/retract individual links? Because I am just trying to get save-form* working for the first time. Right now having problems with it telling me the transaction is empty
1. it does. 2. Just add/remove the data…being careful to make sure new ones have initialized form config. 3. by default tempids are used to figure out if the thing is new or not. Not new == minimal diff
1. Okay, then I guess I'll try to use that! 2. Yes, I looked at the code from the demo to enable/disable accounts. Guess I am missing something because of that "empty tx" error... Now sure where the tx info has to be added or whatever. 3. Good, yes in this case it is stuff that is already in the db. It is pretty much doing what the demo's enable/disable account thing does, but on a custom form
Right now this is how I trigger it:
(comp/transact! this
[(company/toggle-company-approve
{:company/id (:company/id props)
:target-state (not (comp/get-state this :ui/approval-toggle-state))
:tenant-uuid (lib-form/tenant-uuid)})])
And in the mutation I do this:
#?(:clj
(pc/defmutation toggle-company-approve [env {:company/keys [id]
:keys [target-state tenant-uuid]
:as inputs}]
{::pc/params #{:company/id}
::pc/output [:company/id]}
(log/info "TOGGLE APPROVE, inputs:" inputs)
(log/info)
(form/save-form* env {::form/id id
::form/master-pk :company/id
::form/delta {[:company/id id]
{:company/approved
(if target-state
{:after tenant-uuid}
{:before tenant-uuid})}}})
{:company/id id})
:cljs
(m/defmutation toggle-company-approve [data]
(remote [_] true)))
The exact error I get is first "Running txn []" and then "Unable to save form. Either connection was missing in env, or txn was empty."
your code doesn’t make sense to me…the name is “toggle”, so I would expect you to always be setting :after (boolean ___)
Yes, exactly! Sorry. :company/approved is a ref with cardinality :many and I want to add/remove connections from that ref
I think the built-in logic tries to make it match your new list of refs. It assumes you have all of them on screen, and the diff should say what this list was before/after
what you put in the idents depends on how you’ve defined the attributes, but you have to give to-many as vectors of idents.
The point is that in forms in the UI, you’d be managing exactly what you’d have in the normalized fulcro db
The diff for form state is trivial: it is literally the diff (normalized) between what was in state before and after your changes.
so if you ever want to figure out a case, make a form, get it working, and look at what diff outputs…you don’t even need UI…all functions will work on state with ui-less defsc
I have a nested dynamic router, and one of the components under that dynamic router is throwing this error from its :will-enter
when I go to its URL on a full page load (hyperlink after load is fine): "r/target-ready! was called but there was no router waiting for the target listed". is there something with my router setup that i might be doing wrong? sounds like the nested router was supposed to have finished some lifecycle events before my component fired the target-ready
mutation. (BTW, that's getting triggered via a route-deferred
load)
relevant code segment:
(defsc ProjectDetail
[this {:project/keys [id name slug] :as props}]
{:query [:project/id :project/name :project/slug]
:ident :project/id
:initial-state {}
:route-segment (r/route-segment :project)
:will-enter (fn [app {:keys [id] :as route-params}]
(log/info "WILL ENTER: " (pr-str route-params))
(when id
(dr/route-deferred
[:project/id id]
#(df/load! app [:project/id id] ProjectDetail
{:post-mutation `dr/target-ready
:post-mutation-params {:target [:project/id id]}}))))}
For debugging I tried setting a 3s timeout on the load!
:
:will-enter (fn [app {:keys [id] :as route-params}]
(when id
(dr/route-deferred
[:project/id id]
(fn []
(js/setTimeout #(df/load! app [:project/id id] ProjectDetail
{:post-mutation `dr/target-ready
:post-mutation-params {:target [:project/id id]}})
3200)))))}
...but I still got the same error.nothing comes to mind as a sure-thing. Some notes from what I see:
1. Be careful how you use id
. It is always a string when passed to you from URLs
2. Your route segment needs to be a vector that whose prefix is at least one distinct string among siblings.
Hm.. yeah, it's expected here for id
to be a string, and the route-segment here is [:id]
. Must be some small typo somewhere, i'm sure i'll find it eventually
It's written in the book: "If the given router is to be shown on initial startup, then these default routing targets must be singletons (have an ident that does not depend on their props)."
If I'm reading that right, that means it's expected that my component shouldn't work, since its ident is a function of its props? (namely the :project/id
prop)