fulcro

Book: http://book.fulcrologic.com, Community Resources: https://fulcro-community.github.io/, RAD book at http://book.fulcrologic.com/RAD.html
stuartrexking 2020-12-30T02:08:41.408300Z

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?

tony.kay 2020-12-30T03:13:21.409200Z

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.

stuartrexking 2020-12-30T03:54:29.409400Z

Ok. Thanks. I have a half-baked solution on the half-baked RAD implementation. I feel half-baked myself after working through this.

😅 2
stuartrexking 2020-12-30T07:37:47.410900Z

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.

tony.kay 2020-12-30T17:16:38.413700Z

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 actor

Jakub Holý 2020-12-30T08:50:45.411700Z

https://blog.jakubholy.net/2020/fulcro-divergent-ui-data/ is now live. Many thanks to everyone who contributed! ❤️

🎉 3
JAtkins 2020-12-30T17:22:27.420600Z

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.

tony.kay 2020-12-30T17:30:12.426700Z

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

👀 3
Jakub Holý 2020-12-30T17:30:28.426900Z

yes

Jakub Holý 2020-12-30T17:31:06.427100Z

Tony would accept a PR fixing it but I personally do not have time to look into it 😞

👍 1
JAtkins 2020-12-30T17:31:09.427400Z

Ok. I may try to get the project spun up and work on fixing that if someone else isn't doing that already

🙏 1
tony.kay 2020-12-30T17:31:19.427900Z

well, look at that, the entire issues fits here…so, reading it is even easier

tony.kay 2020-12-30T17:32:33.429300Z

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”

Jakub Holý 2020-12-30T17:46:15.429600Z

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?

tony.kay 2020-12-30T18:02:24.429900Z

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”.

👍 3
tony.kay 2020-12-30T18:03:11.430100Z

probably partly because this was the first thing that I saw when I woke up this morning, and perhaps I was a bit cranky 😜

JAtkins 2020-12-30T18:22:19.430800Z

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

nivekuil 2020-12-30T19:22:28.431100Z

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

Björn Ebbinghaus 2020-12-30T20:17:49.431700Z

FYI: There is even a hooks helper namespace: com.fulcrologic.fulcro.react.hooks https://book.fulcrologic.com/#_react_hooks_support

JAtkins 2020-12-30T20:35:01.432Z

Scratch that last note --- not sure what happened, but that particular issue was just a fluke

nivekuil 2020-12-30T20:52:52.432200Z

yup, although for useCallback we actually have access to that "sufficiently advanced compiler" the react docs mention and properly express its intent

tony.kay 2020-12-30T22:03:18.432400Z

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.

JAtkins 2020-12-30T22:05:32.432600Z

dang. and I went to the trouble of making my own...

tony.kay 2020-12-30T22:05:56.432800Z

yeah, I think everyone should look through encore…there’s a lot of useful stuff in there

genekim 2020-12-30T23:05:57.443Z

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!

genekim 2020-12-31T08:14:39.478200Z

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!!

Jakub Holý 2020-12-31T08:45:07.479Z

@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.

Jakub Holý 2020-12-31T08:48:35.479900Z

> 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?

genekim 2020-12-31T08:49:22.480800Z

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!)

genekim 2020-12-31T08:53:51.486800Z

@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!!

Jakub Holý 2020-12-31T09:00:13.487600Z

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

Jakub Holý 2020-12-31T09:01:08.487900Z

Also, Pathom knows nothing about :component/id so you don't want that at all in your query.

Jakub Holý 2020-12-31T09:11:43.488100Z

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?!

Jakub Holý 2020-12-31T09:29:47.488700Z

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

Jakub Holý 2020-12-31T11:04:38.489900Z

@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.)

genekim 2021-01-03T18:36:04.044700Z

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&amp;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",              ;;; &lt;==== NOTE THIS:
   :id "63827c18-5960-408f-8421-66d121a175b2",
   :com.fulcrologic.rad.form/create? false},
  :com.fulcrologic.fulcro.ui-state-machines/actor-&gt;component-name
  {:actor/form :com.example.ui.session-forms/SessionForm},
  :com.fulcrologic.fulcro.ui-state-machines/actor-&gt;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},   ; &lt;===== NOTE THIS
  :com.fulcrologic.fulcro.ui-state-machines/actor-&gt;component-name
  {:actor/form :com.example.ui.session-forms/SessionForm},
  :com.fulcrologic.fulcro.ui-state-machines/actor-&gt;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…

genekim 2021-01-03T18:38:03.045100Z

(…By the way, those state machine states come from the Fulcro Inspector Transactions…)

genekim 2020-12-30T23:27:01.443600Z

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)

JAtkins 2020-12-30T23:31:57.443900Z

You mean this?

(form/edit! this TaxForm (uuid))

JAtkins 2020-12-30T23:40:45.447700Z

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!

lgessler 2020-12-30T23:42:12.449Z

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

genekim 2020-12-30T23:46:12.449700Z

🤯🤯🤯. That's awesome — will check it out later today! Thank you, @jatkin !

👍 1