Fork me on GitHub

Following up from my pairing session with @holyjak — I promised I would post something here for @tony.kay …. when we created a SessionForm that a had an UUID attribute, there was a somewhat cryptic Chrome console message. It wasn’t obvious which attribute was responsible for generating the error — it was the UUID field. (It would have been nice to get an error message like: “no formatter for :session/uuid (of type UUID)“. Screenshot attached.

Jakub Holý (HolyJak)07:12:33

Great you figured it out! Do you have the session/id in the list of the form attributes? I guess you should not because you don't want people to edit it...


For sure, it probably doesn’t make much sense to have the UUID editable…. 😆 but I used it on the assumption that you’d get the same error for any UUID attribute.

👍 3

You need to enable custom formatters


they the error message would have been more understandable because it would have shown you the attribute details


And yeah, there is no UUID form control…you’d have to make one, but that’s easy enough

Jakub Holý (HolyJak)17:12:16

You mean the bintray custom for matters for clojurescript in Chrome, I suppose?


??? That was a bit of word salad to me, @holyjak


Chrome dev tool settings, Console section, “Enable Custom Formatters”


The deps include:

binaryage/devtools                  {:mvn/version "1.0.0"}
will automatically be able to format cljs objects in the console when that is enabled, which will be much easier on the eye in error messages.

Jakub Holý (HolyJak)18:12:31

Damn the autocorrection and not checking my text when in hurry! Sorry for that. Yes, that was exactly what I meant.


@holyjak I spent some time tonight and feel like I almost got mutations working on SessionForm (that we were working on together), using what RAD autogenerated. I think I’m close! I had to change some schemas and dbs around, but now I get this error message: > D 20-12-12 00:58:10 _rad.database-adapters.datomic-cloud:- 98 - Saving form delta {[:session/uuid #uuid “60dd0f5e-7215-40ba-a110-3af30c40b7bf”] > {:session/speakers > {:before “Shaaron A Smith”, :after “Shaaron A Smith SSS”}}} > > D 20-12-12 00:58:10 _rad.database-adapters.datomic-cloud:- 99 - on schema :video > D 20-12-12 00:58:10 _rad.database-adapters.datomic-cloud:-100 - Running txn > [] > > E 20-12-12 00:58:10 _rad.database-adapters.datomic-cloud:-115 - Unable to save form. Either connection was missing in env, or txn was empty. > D 20-12-12 00:58:10 _rad.blob:-206 - Check for files to persist in {:com.fulcrologic.rad.form/id #uuid “60dd0f5e-7215-40ba-a110-3af30c40b7bf”, :com.fulcrologic.rad.form/delta {[:session/uuid #uuid “60dd0f5e-7215-40ba-a110-3af30c40b7bf”] {:session/speakers {:before “Shaaron A Smith”, :after “Shaaron A Smith SSS”}}}, :com.fulcrologic.rad.form/master-pk :session/uuid} The :video schema is correct, and the :before / :after vector is correct. But the txn vector Is empty. I tried calling manually some of the functions in com.fulcrologic.rad.database-adapters.datomic-cloud to see if I could get any insights on why the txn was empty— like wrap-datomic-save and save-form!… but again, my lack of understanding of how the underlying machinery worked impeded any real progress. Do you have any recommendations on an approach? (Your advice of hardcoding the UUID resolver result was awesome — is there some way to do something similar, so that I can perform a mutation event via the REPL, as opposed to going through the web client?). THANKS AGAIN! Latest working state is here:

Jakub Holý (HolyJak)07:12:37

Not sure, since the resolver is auto-generated.. I have to think on it


Awesome — in the meantime, I’ll study how the rest of the RAD demo does mutations, and if needed, read up on mutations in the F3 docs.

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

You could log the inputs coming to save-form! and wrap-datomic-save and compare them to those from a firm that works...


🤯🤯 Roger that! Will do that first thing tomorrow. Thanks again!

Jakub Holý (HolyJak)14:12:07 - perhaps log/store inputs of to-one-txn which I suppose is the relevant one. Also consider re-enabling debug logs. Especially this (and (schema-value? env schema k) (to-one? env k))


Are you sure you put the connections in the env? You have to install the save middleware and give it a properly-written connection resolving function.


(on the server)


• All attributes have to have a ao/schema • All attributes have to be given to the save middleware • The schema of the database has to match the schema of the attributes you plan to save • The connection resolving function you supply has to provide a mapping from schema name to current connection.


@holyjak @tony.kay Holy smokes, thanks for the help — after 2-3 hours of peeking into values inside of datomic-wrap-save and to-one-txn (using tap> and reveal), I finally discovered that the env / attribues didn’t have any of my session attributes installed… …because I forgot to add my Session attributues to the attributes vector. Another big face palm. But OTOH, this has given me about 5 hours of exploration into how underlying machinery works. A bit embarrassed that I could have fixed it without even leaving my session.cljs file… But, feeling AWESOME THAT MY FORM SAVE WORKS!!! 🎉🎉🎉.

bananadance 3

yeah, it is unfortunate I don’t have more time to document…right now you have to kind of carefully comb over each bit of demo to make sure you understand why each thing is done, and if you need it in your circumstance


It’s all good — I’m taking lots of notes, and planning on writing exactly what the steps required are to get my reports and forms working… …and what any surprises were… One of them is definitely what you said: it’s all surprisingly simple, with values being flowed through all the machinery. I think the missing thing is just showing what the major components are, and how they fit together — I’ll share with you whatever I come up with sometime today. Great work on Fulcro RAD. I think it definitely can achieve a “Ruby on Rails” level of magic — meant in only the most complimentary way, of course! 🙂

❤️ 3

(I’m also writing up what dynamic changes can be made w/o restarting anything (datomic-common), and for those that can’t, what exactly is required to be restarted (entire server, server + middleware reload, etc.) That was a source of some frustration, because until today, I wasn’t being very methodical about taking notes, and so kept wondering why my code changes weren’t being reflected. 🙂


There’s a new call that you can make that should update queries on hot code reload…which is a big improvement, but you have to call it in the reload that shadow calls


not sure if that is in demo


It is: (comp/refresh-dynamic-queries! app)


without that (before the remount) queries won’t update….of course initial state is a hard reload (technically you could fix that at the REPL as well, but it would disrupt current app state)


Awesome! By the way, is there a way to test the mutation/save to database without having to use the web client? Currently, the only way that I know how to test if models are correct is logging in, navigating to forms in client, edit, update value, save…. 🙂


certainly, you can just call the parser with a save mutation in CLJ, OR you can use the save-form! from the form ns on the server and hand it a diff


In fact, that’s the easy way to write mutations that need to do something on server when it isn’t a form…write it up as a form diff and hand it to save-form!


writes across all databases automatically 🙂


🤯🤯 Wow! Okay, will give that a try! I know what form diffs look like now! 😂😂


That is so cool. Oh and one more question! 😃😃 Can you point to an example or idiomatic way to have a button that when pushed, tells the server to run a function (eg, do a REST call to an external API): take this session info and update it via the Vimeo API) I see examples of triggering arbitrary actions on the JavaScript client, but not how to call something on the Clojure server.) Thank you!


You mean on a report or form? The controls section. Just make a control button, and have the :action run a full-stack transaction (or do whatever)


you can do that on row action buttons or in control sections.


If you actually mean you want to talk to REST, you could do an http-client thing, or you could make a Fulcro remote that adapts REST API to EQL.


the http-client thing is “ok”…the callback would just call something like Fulcro’s merge-component to put the data in the database.


The “idiomatic way” is to hide that behind a formal remote…you can make a client-side pathom parser that handles that


Got it! I will try to figure out how to make a button in a report or form, and use a control :action to run a function on a server. FWIW, I managed to write a YouTubeVideo set of resolvers in 45m (mostly finding all the right places to record attributes), a corresponding report in 10m, a form in about an hour (mostly hunting down namespaced keywords I forgot to change)… An order of magnitude faster than last time around! This is definitely worth the investment of time it required to learn! (I’ll write up the cookbook I came up with. I’ll be referring to it all the time. Maybe I’ll put it into a public Google Doc…)

❤️ 3
Jakub Holý (HolyJak)13:12:06

Question about - where are the ns com.fulcrologic.fulcro.inspect.websocket-preload and com.fulcrologic.fulcro.inspect.inspect-client (with install-ws) defined? I guess they must be visible to shadow-cljs for the preload / fn call to work yet the instruction say not to add the inspector to the project dependencies. And I do not see them in either. So how is this supposed to work? Thank you!


Adding inspect to the classpath is a bad idea because it is written in F2, which would then confuse the heck out of you by getting offered the wrong nses on autocomplete. Back in the f2 days client was (and still is for f2 users) part of inspect. With the f3 renames, that was not desirable (nor was it ever necessary).

Jakub Holý (HolyJak)19:12:50

I guess I do something wrong

(require '[com.fulcrologic.fulcro.inspect.inspect-client :as ic])
=> nil
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: <eval>:1:1
 Use of undeclared Var com.fulcrologic.fulcro.inspect.inspect-client/install-ws
Or is Fulcro 3.2.12 too early?


always assume an older version is possibly out of sync w/docs


I don’t have a clear memory of that…use the source, Luke 🙂

😂 3
Jakub Holý (HolyJak)19:12:28

thank you. I will finally go and upgrade.

Jakub Holý (HolyJak)19:12:59

Latest RAD is 1.0.8 which depends on Fulcro 3.2.17 while latest Fulcro is 3.4.10. I guess it is save to upgrade to 3.4, right?


if you’re on 3.x, I’d always just use the latest


I do use break versioning for the major number, because sometimes you just get in a corner…but the other two numbers are purely about “amount” of addition/improvement, and should be non-breaking


Fulcro 4 would likely be a new beast altogether, and would not technically break 3, it just would use new names for things but might be API-like…I have no current plans for such a thing, and am pretty happy with where the base design has gotten. There is plenty that could be added, but none should break


So, the major number is sorta hedging my bets

👍 3

I’m building a UI with fulcro’s semantic-ui.factories and so far it’s been a good experience. However, I’ve run into a couple issues: My original idea was to wrap semantic-ui factory in defsc to get the benefits of semantic-ui combined with fulcro’s state management but unfortunately this causes rendering issues. To solve the rendering issues, I separated the state management into a defsc and then I’ve wrapped the factory in a regular defn and the rendering issues appear to be solved. My question : Is there a better approach to combine semantic-ui.factories with defsc without having to create a separate defn to handle rendering? Project code:


Part of the reason I picked SUI to begin with is that the library provides real controlled components out of the box. I’ve never felt the need to wrap them “generally”, as they are almost always used in conjunction with a form, which can be a defsc easily enough. The primary exception is dropdown, which I’ve wrapped in order to do type conversions…see RAD’s semantic ui plugin entity picker.


In specific answer to your question: Anything you put in a defsc that has data deps MUST query for them, or Fulcro will not update them. There are no other specific restrictions. “rendering issues” is rather vague, so I can’t say much more than that


Thanks Tony - I’ll take a look at the semantic ui plugin entity picker and the RenderingOptimizations section.

Jakub Holý (HolyJak)20:12:44

The problem Alex had was that he is nesting two SUI components, Sidebar and MenuItem. If he wraps the menu item in a defsc then it breaks the look and feel, presumably because suddenly he has Sidebar > FulcroMenuItemWrapper > MenuItem instead of just Sidebar > MenuItem and something in SUI expects M.I. to be a direct child of the Sidebar.


Thanks for the clarification @holyjak! 😉