Fork me on GitHub

@holyjak thanks for those…I’d appreciate gathering up a few in the future and submitting one PR 🙂

👍 3

published changes


Can rad forms be targeted? person has an address, but allow a button on the person line item that says add address, which routes you to only the Address form, and leaves all ui for person out.


Looking at the source makes me think no, but I'm kinda hoping that I'm just missing the support 🙂


sorta…depends on what direction the association is modelled


or you can agument save middleware to fix it up


Oh, Gacha. it would need middleware in this case if I understand correctly


If person had a ref to addresses


1. Add a virtual (fake) attr to address as :address/person 2. Send it to the form as initial state 3. In save middleware, capture the fake and rewrite it


Cool, sounds like a plan


you’d make a special instance of address for that, since it would have to declare that as a field


and you’d just hide that field


should work


Cool. Do you keep a list of tips like this anywhere? If not it may be worthwhile to monitor this channel and compile stuff like this from you and others on the channel into a big fqa.


I would love to have more time to document the project, but I don’t 😞


I’ll start watching and compiling stuff like this. I’ll try to tag stuff as I go. Maybe it will be useful :).


I’ll put it in a gh repo

Brian Abbott03:12:14

Just putting some feelers out - is there anyone that might be interested in doing a meetup presentation on Fulcro?


w.r.t? Most likely.

Alex Piers07:12:09

In the process of digging into all the Fulcro materials and would like to share a few thoughts, hopefully helpful to those who are also dipping their toes in Fulcro. Though I've found the videos and the developer guides to be an excellent source of information, the learning curve is very slow at the beginning especially if you do not have prior knowledge on Om Next (not to mention React and GraphQL). However, it is definitely an increasing-returns learning curve when you truly get the point of Fulcro's design. The things that helped me get Fulcro is the Fulcro2 videos which filled in many blanks and guided me to explore Untangled and Om Next. Interestingly, the unlisted and supposedly outdated videos are the most useful. These gems are not easy to find. I only found them while going through loads of Slack chats; these two are my favourites: 1);;list=PLVi9lDx-4C_Rwb8LUwW4AdjAu-39PHgEE , 2) . Until a unified source of Fulcro know-how comes up in the form of new videos or books, learning Fulcro does involve a high upfront investment of time, which I am more than willing to pay, in hope for the long-term benefits. There's so much more to learn and I am just starting to experiment with Fulcro. Look forward to sharing more along the way. P.S. I can watch the videos over and over again, but the sudden loud coughing in a few of the videos may be off-putting to some beginners especially when they are listening intently. This didn't deter me and many others from continuing with the learning, but anyhow, the videos would be literally perfect if the coughing can be edited out. My heartfelt thanks to Tony who is not only an awesome and talented OSS author, but a great and generous teacher!

👍 3

Thanks for the feedback Alex. Sorry about the audio. I don’t have the time to do everything I’m doing and post-edit videos…those are literally single-take, barely-planned and lightly-outlined attempts at giving people info as quickly as possible. The older videos talk so much about the APIs (that are now out of date) that I hid them to prevent confusion for new users. I agree with you on the second one. I really need to re-make that with updated terminology. I have not watched the first one since I made it, so don’t even remember what is in it…but if you found it that helpful I will consider re-making it (or relisting it if it is up to date enough). If anyone would like to volunteer to post-processes this kind of stuff, I’d be more than happy for the help…or if you just know of an automatic post-processing (like a compression setting on ffmpeg or something) that will make loud noises better, let me know. I cannot afford to re-record an entire video because of a cough 🙂

Alex Piers05:12:48

Thanks @tony.kay for replying. Your videos are absolutely helpful and you are a great teacher! A re-make that combines the information of the above two videos with the updated terminology would be excellent. Until then, a re-listing would be really nice, maybe also re-list a few more gems from old times? 🙂 Though not a video expert, I would like to volunteer to post-process your videos including editing out any loud noises, etc. Let me know anytime when you need any video editing. It'd be my great pleasure to help. As for the old videos, there is only one way to edit them without breaking the urls and removing all the views, comments and stats: that is to use the built-in trim function in Youtube Studio. You can find more details here: . This is for your reference only. To save your time, I think leaving the old videos as they are and post-processing any new videos going forward is a good plan. Thank you so much again for taking the time to record all these awesome videos and sharing your knowledge and creation with us.

Jakub Holý (HolyJak)09:12:34

At there is > Add a virtual (fake) attr to address as :sale/account Shouldn't it be "".. to Sale ..."? Also, what is a virtual/fake attribute? One that does not have a field in the db?


Yep on both

👍 3

I hope y'all find this useful. I'll be watching the slack chat for anything that catches my eye. Tag me if you want something specific added. If you want to add material yourself let me know and I'll add you as an editor.


If anyone has some ideas of stuff that's already gone off the chat link it and I'll add it as I can.

Jakub Holý (HolyJak)09:12:08

Update: the proposed solution of using :ui/ready? solved the problem @tony.kay you mentioned that > Attempt to get an ASM path [..] for a state machine that is not in Fulcro state. ASM ID: <some router component> is mostly harmless. To fix, you recommended > You can use app/set-root! with initialize state, then dr/initialize! or dr/change-route!, then app/mount! with NO initialize state to get rid of most or all of those. Basically: Make sure you’ve explicitly routed to a leaf (target) before mounting. I have tried that - in my init fn I have


  (app/set-root! app mb-ui/Root {:initialize-state? true})
  (dr/initialize! app)
  (history/install-route-history! app (html5-history))
  (dr/change-route! app (dr/path-to mb-ui/Intro)) ; overridden in app's on-mount but this makes sure the root router is initialized
  (log/info "App init (almost) dome") ; FIXME rm
  (app/mount! app mb-ui/Root "app" {:initialize-state? false})
however the warning did not go away: > INFO [client:146] - App did mount > DEBUG [com.fulcrologic.rad.routing.html5-history:93] - ["Pushing route" route params] => > WARN [com.fulcrologic.fulcro.ui-state-machines:?] - #error {:message "", :data {}} Attempt to get an ASM path ... ASM ID: :mb.ui/RootRouter > DEBUG [com.fulcrologic.fulcro.ui-state-machines:?] - Trigger :mb.ui/RootRouter So it seems to be a timing issue, the rendering starts right before the router UISM gets started. I suppose the solution is either (1) ignore the warning, it is harmless or (2) add`:ui/ready? false` to the Root and only switch it to true and start rendering anything after the routing system is ready (I guess I could simply (transact! app [(set-ui-ready)]) at the end of init since transactions are executed in order and thus this will run after the UISM start transactions issued by dr/initialize!). Correct? Thank you!


@holyjak correct. The transactions are queued in the default tx processing, so there can be transient flickerings and warnings unless you block rendering until your init is done. You could also try the sync tx plugin, which runs all optimistic stuff synchronously…but it is considered of alpha quality since I have not used it heavily.

👍 3

another thing to say better in the book 🙂


(though I’ve only seen one reported issue, and I think it is mostly harmless):


it’s the only thing “open”…returning false from a remote section causes a problem…I still need to fix that, since in some cases your logic would need to return false there.

Björn Ebbinghaus17:12:18

When making a single load! with :parallel true I get pending... in the network tab in Inspect and I get :com.wsscode.pathom/trace merged into my state. Without :parallel true everything works fine. Any clue whats causing this?


Just seen Rich Hickey's announcement about sponsoring open source devs and I instantly thought of Tony. It turns out that Tony is already in the list of those being sponsored from today on

😻 12
fulcro 21
🎉 9
👏 6

News to me 😄


Nice. That’s really cool.

Alex Piers05:12:17

Here is the announcement: . Apart from the sponsorship, it is also a very meaningful recognition (almost like an award) to Tony and other outstanding OSS developers who have contributed so much to the Clojure ecosystem. Congratulations! P.S. Agree entirely with Rich Hickey's view on this. This is a very good start.

Jakub Holý (HolyJak)17:12:12

Is the display of Diffs in the Transaction tab of Fulcro Inspect (latest chrome plugin, Fulcro 3.4) broken? When I click a uism/begin transaction, I have to click buttons to load the states before and after. I expect the diffs to get updated therearfter but they still show nil even though when I expand the before/after state, they do differ (in the :pending-route :path-segment ). Is it a 🐛 ?


Sounds like a bug. The diffs calculate off of downloaded db revisions, and those are on demand now…must be a bug

Jakub Holý (HolyJak)19:12:39

should I open an issue...?


nah, open a PR if you find a fix. I don’t keep issues around I don’t have time to work on, in general

👍 3

and I don’t

Jakub Holý (HolyJak)22:12:18

But for you diffs in the Transactions list work ok?


@mroerni could be a bug in inspect reporting from Fulcro itself. Does the load work correctly otherwise? (e.g. just an inspect issue?)

Björn Ebbinghaus18:12:37

Yes. It works correctly.


ok, open issue in Fulcro with what happens as best you can describe. Feel free to look through the Fulcro code. Look for uses of ido and ilet…those surround all Inspect reporting. I’m guessing the parallel txn_processing.cljc code is just missing a hook to report the end.


@tony.kay I'm trying to follow the RAD middleware suggestion you talked about earlier, but I'm not sure what kind of transformation I need to do in the middleware, this is what I tried:

(defn account-id-dance [params]
  (update params ::form/delta
    (fn [delta]
        (fn [vals]
            (fn [out k v]
              (if (= k :some-custom-entity/account-id)
                (assoc out :account/_reverse_link
                  {:before nil
                   :after  [{:account/id (or (:after v)
                                             (:before v))}]})
                (assoc out k v)))


but the format was a guess in my part, how it should go?


sorry, lost thread of discussion…did you look at wrap-rewrite-values in RAD? It is an example of making a pluggable mw that can rewrite specific attributes as they are found. The save format is just what form_state.cljc from Fulcro uses.


hey @wilkerlucio can you transact a reverse link in datomic? i thought that was for querying only?


the RAD middleware is supposed to update fulcro's form delta, while still making it look like a form delta, then some code will translate it into a datomic transaction


(defmethod rewrite-value :order/id
     [{user-id :user/id
       firm-id :firm/id} [_ id] v]
     (when (and user-id firm-id)
       (if (tempid/tempid? id)
         (assoc-in v [:entity/firm :after] [:firm/id firm-id])


that's a simple example


that method is defined in


does that make sense?


kind of, we tried changing the format, but getting this error now:

datomic.impl.Exceptions$IllegalArgumentExceptionInfo: :db.error/not-an-entity Unable to resolve entity: [:my.entity/id {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"}] in datom [[:my.entity/id {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"}] :my.entity/year 2020]
data: {:entity
                  {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"}],
                   {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"}]
       :db/error :db.error/not-an-entity}
java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: :db.error/not-an-entity Unable to resolve entity: [:my.entity/id {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"}] in datom [[:my.entity/id {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"}] :my.entity/year 2020]


this is what the form delta looks like:

{:com.fulcrologic.rad.form/id        {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"},
 :com.fulcrologic.rad.form/delta     {[:my.domain.entity/id {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"}]
                                      {:my.domain.entity/year   {:before 2020, :after 2020},
                                       :my.domain.entity/amount {:before nil, :after 1111M}},

                                      [:account/id {:id #uuid "bd99f8e1-a679-4fe7-a82f-090838077bb8"}]
                                       {:before nil
                                        :after  [[:my.domain.entity/id
                                                  {:id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"}]]}}},
 :com.fulcrologic.rad.form/master-pk :my.domain.entity/id}


you've got maps where i think you meant to place UUIDs


{:com.fulcrologic.rad.form/id        #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3",
 :com.fulcrologic.rad.form/delta     {[:my.domain.entity/id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"]
                                      {:my.domain.entity/year   {:before 2020, :after 2020},
                                       :my.domain.entity/amount {:before nil, :after 1111M}},
                                      [:account/id #uuid "bd99f8e1-a679-4fe7-a82f-090838077bb8"]
                                       {:before nil
                                        :after  [[:my.domain.entity/id #uuid "441dc0e4-f4db-456f-9876-a4c6cb4bd2e3"]]}}},
 :com.fulcrologic.rad.form/master-pk :my.domain.entity/id}


^ perhaps that's the delta you wanted?


yeah, working now, thanks 🙂

Jakub Holý (HolyJak)18:12:29

FYI I am still running into an issue where the UI shows the (non-default) router target in an uninitialized state while the router believes that it is displaying the default target. I still cannot figure out why. I have RootRouter > OrgRouter > ... > DetailsDisplayRouter > [LatestBillRunList SubscriberList] and URL .../subscribers and I expect to see the SubscriberList RAD report - which I do, but it is empty, even though the DB has the data, because the parent router believes it is displaying the other report. This only happens when I go to the URL in the browser, not when I click myself through the app to the state. So how is it possible that DetailsDisplayRouter believes it is displaying LatestBillRunList while it should, and the UI does, show SubscriberList?! The state of of the DB seems inconsistent when I compare the router and the corresponding UISM:

uism/asm-id DetailsDisplayRouter:
 active-state :routed
 active-timers {}
 local-storage {:path-segment ["subscribers"], :pending-path-segment [], :target [::report/id :SubscriberList]}

dr/id DetailsDisplayRouter:
 current-route LatestBillRunList
☝️ so the router and its UISM have completely different view of the world?!

Jakub Holý (HolyJak)18:12:24

From the Tx log:

:40 SM(DetailsDisplayRouter) :timeout! :event-data {}
:40 SM(DetailsDisplayRouter) :timeout! :event-data {}
:40 SM(RootRouter) :timeout!
:38 SM(SubscriberList) :event/loaded
:38 SM(OrgRouter) :ready!
:38 dr/target-ready {:target [:org-nr "123"]} ; -> could this confuse DR to believe it shows the default view?! 
:37 SM(DetailsDisplayRouter) :ready!
:37 LOAD subscribers
:36 dr/target-ready {:target [ :SubscriberList]}
:34 SM(BEGIN): DetailsDisplayRouter {:path-segment ["subscribers"], :target [ :SubscriberList]}


right, sounds like a bug in either your code or RAD or DR. If the report doesn’t get a will-enter notification, it won’t start the UISM

Jakub Holý (HolyJak)18:12:38

I believe the report did start its UISM. You can see it did load its data. So all is OK - aside of the confused router

Jakub Holý (HolyJak)18:12:12

And there is even target-ready for the subscribers report. (it is followed by another one, for the ancestor router, no ide why. Perhaps that is messing it up?)

Jakub Holý (HolyJak)20:12:43

I have provided a more detailed description of my inconsistent UI x UISM x router problem in the new GH Discussions I will try to replicate it in the latest RAD demo.


@tony.kay I think would be interesting ot enable the new Discussions tab for Fulcro repository, what you think? did you got the notificaion?


I did not get a notification @wilkerlucio, but it if it persists and allows public interaction, it does sound like a good idea.


the history here is super annoying


yeah, I think you can go to the Settings of the repo and enable it


Thanks for the tip..didn’t know they added that. Let’s see how it goes

👍 3

When using ::form/subforms, how to make the subform items removable?


There are instructions for spining it up in dev mode in, and there are “LANDMARK” markers at the comm spots. I may look at it if I need it…but I never personally use that feature

👍 3
Jakub Holý (HolyJak)08:12:55

so what do you do to check state changes over time, to find out which transaction changed a value in an unexpected way?


Perhaps it is just experience, or perhaps how I structure code, but I rarely find that useful.


Seeing what ran is always useful, but I generally know what things do, so diff is rarely useful


@wilkerlucio added that feature, and I'm sure it helps some, but not really me


so not high prio for me ATM, sorry

Chris O’Donnell23:12:18

@tony.kay Put up a small PR that fixes a minor bug in fulcro-rad-demo: I wasn't sure what branching was appropriate; happy to make any changes that would make things more convenient for you. Thanks for all the work you've put into rad!


cool, thanks!