I’ve added a signup uism to the RAD demo. Once the registering is successful I want to trigger the login flow, without the user having to re-enter their email and password. The LoginForm from RAD transacts the login mutation which remotely checks the credentials and locally in the ok-action checks the status and calls in the RAD auth system for either a success (auth/logged-in) or a failure (auth/failed). I’m not sure what the best approach is here. One idea I had was to have auth/Session as an actor in my uism and replicate the login mutation with a trigger-remote-mutation. Any other ideas for a better approach?
The auth thing in RAD is half-baked. Just write something new. Copy the state machine out of what is there and add some more states and events to it.
Ok. Thanks. I have a half-baked solution on the half-baked RAD implementation. I feel half-baked myself after working through this.
Is there an elegant approach to triggering a change of route from a uism? The examples I’ve seen require app and call dr/change-route directly from a handler.
write a function like this:
(defn change-route-relative [{::uism/keys [app] :as env} router-actor new-route]
#?(:cljs (dr/change-route-relative app
(uism/actor-class env router-actor) new-route))
env)
and make your router an actorhttps://blog.jakubholy.net/2020/fulcro-divergent-ui-data/ is now live. Many thanks to everyone who contributed! ❤️
Are diff added
/ diff removed
broken on the new versions of inspect? I'm seeing nil
everywhere, but it could just be my stuff being stupid.
I have a request of this community. I’m a bit irritated by a recent GitHub issue and I’m trying to be as nice about it as possible; however, it has touched a nerve and I’d like your participation in addressing it. First, I’d like a little bit of understanding: I built Fulcro for my projects and my startups. I work 12-16 hour days. Many of those hours, as you can imagine, are spent refining Fulcro, documenting things, and answering questions. The first two I do out of partial self-interest: it makes it easier to onboard help in my own projects to have good docs, and I use Fulcro for practically everything I write. The last one, though, I do because I enjoy helping people. I am not Facebook. I don’t get paid billions of dollars selling your kitten memes to advertisers. I benefit from open-source, and so this is one way I “give back”. It is highly optional, very non-lucrative (I do make some money from free OSS, but it amounts to waaaaay less than minimum wage, and way less than I charge for my time professionally). A thank you goes a long way, and help is appreciated. But some days I have a very clear and personal understanding of why open-source projects get abandoned. There is no economic model for doing this. Businesses, on the whole, don’t pay even 0.001% of the benefit they get from OSS. So, this means that most OSS is pretty much a volunteer effort. That means that every issue you open or request you make takes a little bit of my time. So, here’s my request: Could each of you read this issue (it’s very short, and I think well-intentioned), think about how that might land on your average open-source maintainer, and gently and nicely add a comment to that issue that improves our shared understanding before I close it (or retitle it)? https://github.com/fulcrologic/fulcro-inspect/issues/97
yes
Tony would accept a PR fixing it but I personally do not have time to look into it 😞
Ok. I may try to get the project spun up and work on fixing that if someone else isn't doing that already
well, look at that, the entire issues fits here…so, reading it is even easier
My apologies to the the person that opened the issue. I realize this might be a little embarrassing. I have no personal hard feelings toward you at all. I just have a need for people to be a bit more enlightened. Forgive me for using your issue as a “teaching moment”
I feel your pain. But the average user doesn't see it, maybe they believe Fulcro is a community effort and not the heroic deed of mostly a single person. Perhaps it would help to define an issue template or some pre-issue checklist that would summarize ☝️ and explain when (not) to open an issue?
Sorry, that’s all the time I’ve got for this. Not asking for a solution to people opening issues in the future. It’ll happen again no matter what I do. That’s OK. It’s normal. I’m doing something very unusual: Asking for people to do a bit of self-reflection in the “now”.
probably partly because this was the first thing that I saw when I woke up this morning, and perhaps I was a bit cranky 😜
There seems to be a 2nd regression as well - looks like the db
tab is treating state as (seq {state stuff})
and goofing up when you click an index to add to watches
I just learned about useCallback
: https://reactjs.org/docs/hooks-reference.html#usecallback worth a mention in the book? https://book.fulcrologic.com/#_callbacks_causing_over_rendering
FYI: There is even a hooks helper namespace: com.fulcrologic.fulcro.react.hooks
https://book.fulcrologic.com/#_react_hooks_support
Scratch that last note --- not sure what happened, but that particular issue was just a fluke
yup, although for useCallback we actually have access to that "sufficiently advanced compiler" the react docs mention and properly express its intent
it’s also worth noting that if you use timbre, you already have encore, and encore has a memoize that will GC and can have a TTL. It’s a much easier thing to use that gets you 95% there with no need to even “name” your dependencies.
dang. and I went to the trouble of making my own...
yeah, I think everyone should look through encore…there’s a lot of useful stuff in there
After watching all the remaining Fulcro 3 videos, and studying the code examples, a bunch of the concepts became much clearer — and I have finally created my first F3 components, as opposed to using the Fulcro RAD forms and reports.
But I’m still struggling to understand how to access all the F3 entities from inside RAD reports and forms. Taking a stab at articulating clearly my questions:
1. When inside of a RAD report, how do you access data outside the report, such as the “global” components that are often stored in [:component/id]
in so many of the F3 examples. (e.g., [:component/id :person-list :person-list/people
or like here: https://github.com/fulcrologic/video-series/blob/forms-final/src/app/client.cljs#L118. (I tried adding them via ro/query-inclusions
, but could never get it to show up in props
2. How can one use a RAD form from an F3 component? For example in the “forms-final” example, how would we leverage a RAD form for Undo/Save functionality to edit ItemDetails, instead of writing all of it ourselves?
3. (Maybe the easiest question, which would illuminate #2 above): how does one edit a specific entity in a RAD Form, say, a specific invoice, in the RAD example. Currently, the only way to reach them seems to be via ro/form-links
— how does one edit a specific invoice, say by its UUID?
Thank you, all!
This really is incredible, @tony.kay!!!! The ability to have multiple RAD forms on the screen is so freaking cool, and makes it so easy to use the form machinery you've created!
Is there a way to have a RAD Form access things like {:component/id :person-list}
? I'm trying to replicate some of the "video-series" examples you created with RAD, but can't figure out how to reach those "global state" things... Thx!!
@genekim please consider sending a PR to the RAD book to make it easier to discover form/edit!
etc.
Somebody (you?) could perhaps also write a section on "Using Forms outside of a router" 🙂
For reports it is perfectly OK to use them outside of a router but you need to start their UISM manually. I guess you just need to look at what the form/report :will-enter
does.
> s there a way to have a RAD Form access things like `{:component/id :person-list}` ?
ro/query-inclusions
should work, provided you write it right, I believe. What does your look like? After adding it, look at the outgoing Network request - does the query look the way you expect? What about the response?
Will do in the next week, @holyjak ! (And thanks for solving the mystery of why the form didn't look quite right... Looking at the screenshot, I noticed that it hadn't fully populated yet! Nice!)
@holyjak Okay, I love that like ro/query-inclusions
is likely the right mechanism! I had tried adding something like ro/query-inclusions [ [{:component/id {:person-list {:person-list/people [id, name]}]
-- but it seemed like everything I put in resulted in nil
everywhere. It should be an EQL query, which can be tested in Fulcro Inspector, yes?
It occurs to me that I should have studied what the results of (comp/get-query)
and (comp/get-ident)
were. Will pick it up again tomorrow! Thx!!
that is wrong. You are trying to add a join on the :component/id
property of current entity and there is no such thing, I think. Look at https://book.fulcrologic.com/#_link_queries
Also, Pathom knows nothing about :component/id
so you don't want that at all in your query.
Hm, I have problems getting ro/query-inclusions
working on latest rad-demo, it does not add it to the query sent to the backend...
1. I added ro/query-inclusions [:category/all-categories]
to the RAD demo InvoiceList
report
2. (comp/get-query com.example.ui.invoice-forms/InvoiceList)
has the added part: [:com.fulcrologic.rad.report/id ... :ui/current-page [#:ui{:current-rows [:account/id ...]} ...] :category/all-categories]
3. (df/load! com.example.client/app :invoice/all-invoices com.example.ui.invoice-forms/InvoiceList)
sends the query including the added part, like this:
[{:invoice/all-invoices
[:com.fulcrologic.rad.report/id :category/all-categories]}
:com.wsscode.pathom.core/errors]
but the query sent by the report when I reload the page is different:
[({:invoice/all-invoices
[:account/id
:invoice/id
:invoice/date
:account/name
:invoice/total]})
:com.wsscode.pathom.core/errors]
so it has more stuff in the query but lacks the added stuff. I guess the report UISM load event does something weird to the query...
That is because it loads the data differently:
[({:invoice/all-invoices
[:account/id
:invoice/id
:invoice/date
:account/name
:invoice/total]})
:com.wsscode.pathom.core/errors]
see https://github.com/fulcrologic/fulcro-rad/blob/d81892cabdcb3b48d4f95c763414f5ff1c9c7bdf/src/main/com/fulcrologic/rad/report.cljc#L161
So this uism/load is good b/c it includes the BodyItem query needed for the report but it is bad b/c it ignores the query-inclusion. Is this a bug? Should ro/query-inclusions
be added here as well?!Now I realize that also the query produced by df/load! is not what I expected (and I was wrong to expect it). Of course it puts the attributes into the join:
[{:invoice/all-invoices
[:com.fulcrologic.rad.report/id :category/all-categories]}
:com.wsscode.pathom.core/errors]
b/c that is what load! does when provided with "server-property". So I would need to make sure that the resolver for :invoice/all-invoices
returns whatever extra properties I want to request.
(And I still do not understand how ro/query-inclusions
is supposed to be used given that report/reload
/ report/load-report
does send a different query, one without it.)
I guess it could work if the properties I ask for were returned by the all-invoices resolver and I issued a manual df/load! - then it would be loaded and stored in the client DB. The report UISM would subsequently issue its own load to load the actual report data itself so that both would be in the DB. Then I guess props would contain both... But I need to look at what exectly report's :will-enter
does@genekim I thought more about it and perhaps I have the answer to #3.
You use ro/query-inclusions
. If the data is already in the client DB then you are good. If not, you need to df/load!
them manually, e.g. as shown above.
To access :component/id :person-list :person-list/people
in this way you must remember that the query is relative to the report's position in the data tree (which is a subset of the ui tree). Only the Root can ask directly for {[:component/id ..] [..]}
in its query. Any nested component must use https://book.fulcrologic.com/#_link_queries to reach it. So something like
ro/query-inclusions [{[:component/id :person-list] [:person-list/people]}]
;; or st. like: [{[:component/id :person-list] (comp/get-query PersonList)}]
should do the job (here I leverage a join on an ident https://blog.wsscode.com/pathom/v2/pathom/2.2.0/connect/resolvers.html#SingleInputs to get at the particular component)
(Use get-query
on the Root
or the report component to have a look at the query and check that it looks OK. Remember you can turn the query into the resulting data tree manually.)This is great, @holyjak — I had intended to study your ro/query-inclusions
example this weekend, but ended up spending 4 hours trying to figure out how to get the UISM machinery started for forms not started via router: https://clojurians.slack.com/archives/C68M60S4F/p1609404307479000?thread_ts=1609369557.443000&cid=C68M60S4F
> For reports it is perfectly OK to use them outside of a router but you need to start their UISM manually. I guess you just need to look at what the form/report :will-enter does.
I tried using (form/start-form!)
, and it took me a day to figure out where / when to call it. (I put it in the same place where the df-load!
went.)
My problem now: when I edit the form, the “Save” or “Undo” briefly flicker on, but then get disabled… Edits to the data show up outside the form, too…
Movie of this happening here: https://www.dropbox.com/s/ogqoey8r9m58kbv/Screen%20Recording%202021-01-03%20at%2010.31.00%20AM.mov?dl=0
My current theory: something in the Form UISM was set wrong? Here’s the state from the demo app: Area of difference shown with a “<====”
- com.fulcrologic.fulcro.ui-state-machines/begin
{:com.fulcrologic.fulcro.ui-state-machines/asm-id
[:session/uuid #uuid "63827c18-5960-408f-8421-66d121a175b2"],
:com.fulcrologic.fulcro.ui-state-machines/state-machine-id
com.fulcrologic.rad.form/form-machine,
:com.fulcrologic.fulcro.ui-state-machines/event-data
{:action "edit", ;;; <==== NOTE THIS:
:id "63827c18-5960-408f-8421-66d121a175b2",
:com.fulcrologic.rad.form/create? false},
:com.fulcrologic.fulcro.ui-state-machines/actor->component-name
{:actor/form :com.example.ui.session-forms/SessionForm},
:com.fulcrologic.fulcro.ui-state-machines/actor->ident
{:actor/form
[:session/uuid #uuid "63827c18-5960-408f-8421-66d121a175b2"]}})
And here’s the form that I set up manually thru form-begin!
- (com.fulcrologic.fulcro.ui-state-machines/begin
{:com.fulcrologic.fulcro.ui-state-machines/asm-id
[:session/uuid #uuid "8a481331-eb1d-4e5b-9d19-759da23cb674"],
:com.fulcrologic.fulcro.ui-state-machines/state-machine-id
com.fulcrologic.rad.form/form-machine,
:com.fulcrologic.fulcro.ui-state-machines/event-data
{:com.fulcrologic.rad.form/create? false}, ; <===== NOTE THIS
:com.fulcrologic.fulcro.ui-state-machines/actor->component-name
{:actor/form :com.example.ui.session-forms/SessionForm},
:com.fulcrologic.fulcro.ui-state-machines/actor->ident
{:actor/form
[:session/uuid #uuid "8a481331-eb1d-4e5b-9d19-759da23cb674"]}})
Going through the source code now to see where and how event-data
is set…(…By the way, those state machine states come from the Fulcro Inspector Transactions…)
For instance, I’d like to use a RAD form to edit PersonDetails, like here: https://github.com/fulcrologic/video-series/blob/full-stack-over-time/src/app/client.cljs#L19
I can imagine implementing this by accessing the [:component/id :person-list :person-list/people]
, but how does one access this from inside a RAD form? (Question #1)
I can also imagine using rroute/route-to
or something to edit a specific entity, but how? (Question #3)
Or maybe there’s a way to use RAD form functionality from within an existing F3 component (like PersonDetail
), but how? (Question #2)
You mean this?
(form/edit! this TaxForm (uuid))
I can't speak to #1 yet, I've not tried anything like that to date. For #2, perhaps you are looking for formstate? https://book.fulcrologic.com#FormState
For #3, you would want to look at the com.fulcrologic.rad.form
ns, specifically create!
and edit!
does anyone have a strong opinion about whether keywords used for data (so, ones appearing in the fulcro db or in pathom resolvers/mutations) ought to have "full" namespaces? in general clojurians tend to prefer "full" namespaces like :com.mycompany.widget/id
, but it's common at least historically for fulcro projects to use :widget/id
. Personally while I'm sympathetic to the best practice of using full NSes in general, a major reason for this practice is to avoid name clashes, and if your app is never going to be a dependency for another system, and data flowing into your app won't clash with abbreviated namespaces, then I wonder whether abbreviated namespaces might be harmless and perhaps even preferable for certain kinds of readability
🤯🤯🤯. That's awesome — will check it out later today! Thank you, @jatkin !