This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-06-02
Channels
- # announcements (37)
- # babashka (9)
- # beginners (172)
- # calva (7)
- # cestmeetup (28)
- # chlorine-clover (27)
- # clj-kondo (2)
- # cljs-dev (45)
- # cljsrn (8)
- # clojure (185)
- # clojure-dev (27)
- # clojure-europe (6)
- # clojure-finland (3)
- # clojure-nl (5)
- # clojure-uk (13)
- # clojuredesign-podcast (4)
- # clojurescript (54)
- # conjure (19)
- # core-typed (1)
- # cursive (40)
- # datomic (9)
- # emacs (5)
- # figwheel-main (34)
- # fulcro (238)
- # graphql (14)
- # hugsql (3)
- # leiningen (4)
- # malli (6)
- # off-topic (12)
- # pedestal (5)
- # portkey (19)
- # protorepl (8)
- # rdf (2)
- # re-frame (23)
- # reagent (3)
- # reitit (16)
- # shadow-cljs (29)
- # spacemacs (12)
- # sql (1)
- # xtdb (15)
So, the RAD Routing... what do I do if I can't import the namespace of whatever I want to route to? It seems like just giving the fully qualified name (like com.example.accountpages/Overview
) in quoted form does not work
Also I have not found out what exactly triggers the ::uism/started
event in a state machine state. It seems it only gets triggered when I make shadow-cljs re-send the compiled js code, but never on initial page load
Speaking of RAD? I think it is sent when you route to the report/form. I remember I had to start it manually when I wanted to use a report outside of a router.
No, independent of RAD, but I am using RAD. I do manually start the uism for authentication stuff, but right when loading a page it will stay at :initial
until I either click a link or load new code
Any hints would be nice, because I spent way too much time already with this... Pretty sure I did something wrong, because I'm not the only one using this. I use the state machine from the fulcro template
started is sent on calls to begin!
, which is done in RAD on routing will-enter (i.e. you have to trigger a route). There is also a function you can call to start the report or form in each respective ns if you are not routing to it
Oh well then I think it should work? I have the call to uism/begin!
in the init function in client.cljs, just like it is in the fulcro template as well as the RAD demo.
But what is currently happening is that it is "stuck" at the :initial
state until I either update the app by saving a file, or I click something that triggers routing.
Same happens after login with the :state/checking-session
state. It seems it only goes one step each time.
When the page loads it is at :initial
and stays there. As soon as I update, in this case by clicking on my Login (separate page), it goes to :state/logged-out
. When I log in, it loads the next page and then is at :state/checking-session
, until I click something else at which point it goes to :state/logged-in
. As soon as I refresh the page with F5, it is back at being stuck at :initial
until I update.
By having a (dom/p "Current UISM state: " (str (uism/get-active-state this ::authorization/session)))
on the page. Quite crude, but gives the same result as logging it
Also, when refreshing on the login page, I get an error when trying to login because the uism is in the wrong state
As far as âauthorityâ on state goes: Using a REPL to inspect the app ::app/state-atom
is always right. Inspect is most likely right as well (it give up if it detects out of sync and goes blank). Rendering is not reliable, since React can optimize away an update
The way I even noticed this was because my login form would break when accessed directly. A look in the console confirmed my suspicions because there was an error from uism that there is no such event in state :initial
Hmm okay I figured it out now... No idea why that would cause such a thing, but I didn't use the same routing function everywhere. Most places were RAD's route-to!
but I still had normal Fulcro's matching as well.
@tony.kay I run again into the issue where a report is empty after hard-reload of a page, despite the data being fetched. I'd love to help fix this but I need your advice on how to troubleshoot it.
Facts so far (90% confidence :)):
⢠It happens for the second report and not the first one under the same router
⢠It happens nearly always in release build, rarely in dev build
⢠Fulcro can see the data - (->> (db->tree (comp/get-query SubscriberList) [::report/id :myns/SubscriberList] (app/current-state APP)) :ui/current-rows count)
returns > 0
⢠It doesn't seem to be a rendering issue - I use keyframe-render2 and (app/render! app {:force-root? true})
has no effect
Where should I look? đ
Sounds like a timing issue to me. In dev there is a lot of stuff adding overhead, so things move more slowly. In release, they are much much faster.
also not sure what you mean by a hard reload of the pageâŚyou mean: if HTML5 routing is used to get there? Or do you mean, you reload, then click to go there?
@U0522TWDA you still around?
Also, is this a âdefault routeâ? It could be something related to that as opposed to anything at all to do with the report.
I am here. HArd reload is Cmd+Shift+R. I am using RAD with its history API / url integration
So, are you set up where you can edit the source of RAD itself, like here https://github.com/fulcrologic/fulcro-rad-demo#running-from-source ?
An alternate route - that is what I meant that it works for the first report (route) but fails in this way for the second report=route
I donât mind helping, but I would like to be efficient. If you know when youâre available in realtime, let me knwo
My default page (no route in URL) is an empty page. when I type the url /org/123
then the first report is displayed, with data. I click a link there to go to /org/123/subscribers
, which replaces the report with a list of subscribers, which works. I Cmd+Shift+R on this page - and now the subscribers list = report is empty.
I am available in realtime now
ok, and when you look at the state, it seems all linked upâŚyou said current rows is populated
I.e. hard-reload on the non-default route /org/123
works but not on /org/123/subscribers
.
Yes, the state looks ok.
No special console messages except for the warning The actual inputs (:bill-run/id :br-subscriber/subscriber-id) on minbedrift.ui.kostnadsdeling.ui/SubscriberList do not match the declared layout: [[:br-subscriber/subscriber-id]] (I have a param I dont want the users to set themselves)
Iâm assuming from earlier messages that you ahve a hard time making it not work in devel
I have right now open the page in dev where the error did exhibit so I can look at any state etc to troubleshooti t.
Also, you can use production react js in development as well, using shadow cljs resolve settings (like shown here: https://github.com/fulcrologic/fulcro/blob/3.2.8/shadow-cljs.edn#L23)
Actually, I do manage to replicate it in dev now it seems. No errors, only the 3 warnnings about "The actual inputs .."
Iâd also look at the other bits of state: is pagination enabled? Does the pagination stuff look right? Is the row data âsaneâ? Are you using row transforms?
No transform, no pagination, data looks ok. According to db->tree
and Fulcro Inspect it has data
I have copied the state DB from the case of empty report x correct report and am looking at their diff
Here is a significant difference: in the OK report I have
:com.fulcrologic.fulcro.routing.dynamic-routing/id
{:minbedrift.ui.kostnadsdeling.ui/DetailsDisplayRouter
{:com.fulcrologic.fulcro.routing.dynamic-routing/id
:minbedrift.ui.kostnadsdeling.ui/DetailsDisplayRouter,
:com.fulcrologic.fulcro.routing.dynamic-routing/current-route
[:com.fulcrologic.rad.report/id
:minbedrift.ui.kostnadsdeling.ui/SubscriberList],
in the BAD case I have
:com.fulcrologic.fulcro.routing.dynamic-routing/id
{:minbedrift.ui.kostnadsdeling.ui/DetailsDisplayRouter
{:com.fulcrologic.fulcro.routing.dynamic-routing/id
:minbedrift.ui.kostnadsdeling.ui/DetailsDisplayRouter,
:com.fulcrologic.fulcro.routing.dynamic-routing/current-route
[:com.fulcrologic.rad.report/id
:minbedrift.ui.kostnadsdeling.ui/LatestBillRunList],
(where DetailsDisplayRouter is the parent router of the first/second report and LatestBillRunList is the "first" report and SubscriberList is the "second" report)Yes, the current route looks wrong. The UI does display the expected SubscriberList. I will look at the Transactions history to try understand it...
What should I look for?
ok, will do
thanks a lot!!!
At some point I really want to change the dynamic router and drop the deferred route support. It sounded like a good idea, but I think its the source of a lot of headaches.
Here is the event list, but it doesn't tell me anything...
I have three nested routers: Root > Org > DetailsDisplay (parent of LatestBillRunList [default] and SubscriberList)
1. Begin RootRouter
2. Begin OrgRouter
3. Begin DetailsDisplayRouter
4. Waiting OrgRouter
5. Waiting DetailsDisplayRouter
6. [load data for OrgRouter target]
7. Begin SubscriberList
8. df/target-ready SubscriberList
9. [load SubscriberList data]
10. ready! DetailsDisplayRouter - here its current-route
becomes [nil :myns/SubscriberList]
(was [nil :myns/LatestBillRunList]
) state after has :current/route [:myns/SubscriberList]
11. df/target-ready [org "123"] ( OrgRouter target) - weirdly, state before has DetailsDisplayRouter :current-route [:myns/LatestBillRunList]
?!
12. timeout! OrgRouter
13. :event/loaded SubscriberList
14. ready! OrgRouter
Maybe I am the cause of the issue, in this code:
(defrouter DetailsDisplayRouter [this {:keys [current-state]}]
{:router-targets [LatestBillRunList SubscriberList ChargeList Empty]}
(case current-state
:pending (dom/p "Loading...")
:failed (dom/p "Failed loading details")
(do ;; :initial / nil: no route selected yet, route to the latest bill runs & show nothing in the meantime
(routing/route-to! this LatestBillRunList (comp/get-computed this))
nil)))
Here I explicitly route to the default route when no route is selected, because I experienced problems when the route wasn't explicit. Perhaps I do it wrong and screw things up?Ok, I won't. But removing it has no effect on the problem. Yes, OrgRouter resolved after its child.
Though I did the same thing in the OrgRouter (if no route, route explicitly to the default target). I removed that and now it seems to be working just fine...
Or actually not, 4th reload ended up with the problem again
OrgRouter is still the last one to get ready!
BTW the URL contains the report param I call here org
, which both OrgRouter and DetailsDisplayRouter use. I guess that, as the url is processed by the routing system, that is why OrgRouter is forced to redo its thing. Why it finishes last I dont know.
Since OrgRouter is :routed
last, and its target has LatestBillRunList
as its default target, could it be somehow that it overrides the current route of its child's router (DetailsD.R.) to be its initial/default value?
@tony.kay I have discovered one really weird thing. In the transaction list above, the state after at point 10 is :current/route [:myns/SubscriberList]
yet the state before of the next point 11 is :current-route [:myns/LatestBillRunList]
How could this be possible that the state changes between two consecutive transactions?!
Iâm concerned about possible deferred routing stuff. The way that all has to work is that each layer of the route could defer, and that (I think) delays the routing process. Itâs too much for me to even thing about at the momentâŚother things going on. The side-effecting in render is badâŚyou should definitely not do that. Otherwise, not sure what might be wrong
Yeah, I have removed the side-effecting. Any tips for troubleshooting how can the current-route change between two transactions and what caused it?
hmâŚhaving trouble figuring that out myself. I mean: the state machine itself is a big mutation
FYI I have add-watch
to the state atom and the swap! that screws up the current-route (changing it back to the default target) also seems to set the data load!
-ed by the middle router's target, i.e. OrgDashboard (I have synchronous RootRouter -> OrgRouter with a deferred route to OrgDashboard -> DetailsDisplayRouter that has targets BillRunsList (default) and SubscribersList (which I expect to see)). Perhaps the effect of the load! and the subsequent :post-mutation
dr/target-ready` happen in the same swap! and it is this post mutation that kind of resets the child router - DetailsD.R. - to show its default target again?
As noted before, the last transaction is ready! OrgRouter
, which would match this fact.
Also, when things work out correctly and the SubscriberList is not only showing but also the current-route and has the data, all the transactions are the same except the newly inserted 13:
⢠12. timeout! OrgRouter
⢠[new] 13. timeout! DetailsDisplayRouter
⢠14. :event/loaded SubscriberList
⢠15. ready! OrgRouter
@tony.kay what do you think about âď¸ ? Could it be the target-ready
postmutation of the parent deferred component that leads to the reset of its router back to the first target (overriding the expected current-route)?
yeah, the timeouts should be causing a state change to display the âroute pendingâ state. If thereâs a bug there, you could always up your timeouts on change-route to something large and just not use that feature.
What are the advantages of each of these? (Sorry for the handwriting - passenger one a car rn.)
What are important tells that one should be used over the other? In my head Iâm imagining that the translation on the server is more favorable, but Iâm not sure why I think that.
Iâll try to mention the main ones that come to mind: ⢠Whose CPU does the work? ⢠Who has access to edit the code of the network service? (do you own the server?) ⢠Where might you want to build in caching? Do you want an offline mode?
the translation layer in the UI also tends to be more abusive to overall low-level I/O resources, since no back-end optimizations can typically be applied.
so you might over fetch to get the result you wantâŚand I/O resources on server are a typical bottleneck; however, with significant client caching you can go the other way easily.
So, just for context - I have used reframe heavily in the past. In fulcro I sorely miss some of the features, though on the whole it is a good trade. Right now Iâm thinking about what it would look like to join the two models.
I would love to hear what specific features youâre missing, and how we might address that.
âsorely missingâ can also just mean âdonât know how to do it easily in the new tool Iâm usingâ
The subscription graph - keeping data in sync is hard with fulcro. Iâm sure itâs just me missing out on all the advances in the java swing world (mvc and stuff), but properly invalidating derives data is tough. It is drop dead easy in reframe.
Both. Also, some parts of my app have several dynamic invalidation queues - much easier to detect in re-frame natively. I'm not worried about the formula being in the render for time sake - I can do caching in another layer. But knowing when to re-calculate is hard.
(I did end up coding a system somewhat like re-frame inside fulcro, but it is not nicely integrated. I'm interested in a cleaner integration.)
As a general statement - I think subscription graphs are a very very nice model to maintain simplicity in the ui code.
But reframe also tends to create non normalized databases without careful work, so mutations become very difficult.
Maybe I misunderstood. Yes, the graph in reframe is super nice for caching. You no longer depend on top level changes only - derived middle layers can filter data such that no change is detected and the calculation is halted.
got itâŚso, I think perhaps using re-frame for that part might be something to consider. Iâve been toying with the idea of a hybrid myself.
I just had an insight on how to make a pretty nice proof of concept without much work. Iâll ping back here once I get a chance to make it. Should be in a week or 2
ok. I mean, the tx processing system of Fulcro is extensible. Ideally, adding such a mechanism would go in there. That would make it a seamless integration
Some of the initial thoughts - subscriptions are inherently more powerful than the current system in fulcro for ui derived data. (not that anything in one is not possible in the other, but subscriptions are a good model). The fact that fulcro creates the entire data tree to match the ui is cool, but un-necessary. Each component could side-load it's data from subscriptions. Imagine re-frame having a macro that creates a query. This macro does 3 things: First, it adds the component to fulcro's registry so db->tree works. 2nd, it adds a subscription generator that given the component ident returns a new subscription that has the normalized contents of the db entry. 3rd, same as #2 but returns the denormalized db entry.
I think the way subscriptions in re-frame are handled would actually have to change slightly for this to be fast.
In fact - just reading the re-frame docs I came across this. http://day8.github.io/re-frame/reusable-components/#derived-identities Kinda how I got myself in trouble the last app I made.
So, there are pros and cons to everything. The joined tree of UI in Fulcro is not necessary: see floating roots. The only feature that currently uses the joined tree (globally) to good effect is Dynamic Router, and that could be done differently; however, note that subscriptions also have a lot of problems and challenges. The joined tree is also used by forms, but that is just a sub-treeâŚthere is no reason, per-se, for that subtree to need to be joined to the parent.
Remember that Reframe is largely concerned with non-distributed concerns: its a front-end library that you can side-effect fromâŚNothing gets you away from the complications of data loading except a meteor-like db sync (which moves the complexity to a layer you donât control, and which is really hard to get right while also being scalable).
The âjoined UI treeâ in Fulcro is an inconvenience that floating roots address for the cases where it actually hurts you. Subscriptions (NOR) floating roots solve the harder problem: When do you load the data? How do you keep it in sync? What if two different components need different subsets of the same normalized data?
And for those cases I would argue that you want that logic to be lightly coupled in a small space with an easy ability to comprehend and trace it. Disconnecting it will create much more difficult problems to solve for a very minor initial convenience.
I would encourage you to learn how to write the thing youâre trying to get with the features Fulcro provides. Get good at that, and then try to design an improvement; otherwise I fear youâre thinking too much about a âfeatureâ than an actual scalable development practice: Iâm interested in the latter, and only care about the former when it becomes obvious that it will somehow help with the latter âon the wholeâ. Developers tend to concentrate too much on convenience first without thinking more long-term.
I love convenienceâŚdonât get me wrongâŚI just think emphasizing it too early is a big mistake.
âsubscriptions are inherently more powerful than the current system in fulcro for ui derived dataâ is a subjective opinion. They are a feature youâre used to that you happen to like to code that way. They have trade-offs in both directions (some things are easier, some are harder).
Derived UI data is another one where youâre perhaps concentrating on a particular feature without thinking through all of the implications.
Why is it more powerful? What are you comparing, exactly? Iâd agree with you that the signal graph system of reframe has more features for derived data that Fulcro has (out of the box). Does that scale well? Do teams reason about it over time on large projects well? Can you trace the code, or do you have to âgrepâ for keywords to find things? How do you understand what youâre getting? Can your IDE navigate to the definition of what is goign to happen for that subscrition? Do side effects from one affect another? How?
(Please understand these are real questions. Iâd love to have more powerful tools that are also scalable on teams. Iâm open to debate here, so please donât think Iâm taking an aggressive tone. I struggle with these questions all the time and would love to see us evolve thingsâŚIâm just trying to frame the questions and solutions with the constraints Iâm interested in) đ
So, for example, the question âCan your IDE navigate?â can easily be solved with a simple def of a symbol next to the thing (def delete :delete)
next to the handler for the :delete
operation lets you use that symbol to then get code nav from uses of it.
It requires a bit more developer discipline, but turns a grep into a quick nav, and making a macro that turns it into a convenience gets you both (which is just what defmutation
is in FulcroâŚa defmethod
that is navigable)
same with subscriptions: you can get tool help like âfind usagesâ that are a lot more accurate if it is either a namespaced keyword or a proper sym. Teams need these kinds of things to comprehend the code. If the tool feature doesnât have that, then it is a problem.
UISM in Fulcro has this problem: it is event-based. It is harder to trace as a result. Fortunately, it is an âenclosed unitâ. All of the events are defined in one small code unit. Iâve not yet made macro wrappers for making events to make them more navigable (because SMs are meant to be reusable in complex ways that I have not fully analyzed for making such a macro be a library quality feature). But code I write with UISM has the undesirable property of creating a hard-to-navigate without good discipline, meaning a team will possibly not scale well with that feature.
In practice, I find that UISM is harder to work with in some ways than just plain mutationsâŚbut it concentrates a different âglobal concernâ into a unit that is easier to reason about. So, trade-off. I lose some of the goodness of perfectly IDE nagivigable and traceable mutations for a system that instead makes it easier to comprehend the âoverall logicâ of a subsystem when Iâm looking at the SM definition.
Ok, I see where you are coming from. Just a bit of background on me - I've been writing CLJ for 3 years, and am in my 1st year of professional development still. (jr in college, whatever that's worth.) So, I don't really have the background w.r.t. teams that you or most of the people here do. The primary advantage I have here over most of the community is that because I'm in college I have alot of spare time to toy around with ideas. But, that still leaves me with things that I can't really think about in context, having never worked on a large team (I currently manage a project of 3 devs on a fulcro project). I'm always interested in hearing how/why stuff works or doesn't work in large teams, or at long development timescales, or at large production. Back to the discussion here with that in mind: the reason I think that reframe is more powerful in this position is that I can see a full implementation of fulcro's db management easily created within the parameters of re-frame. I don't see a corollary the other direction.
Also, I don't think there is any loss from using the result of the merger, but I could be wrong
So, youâre talking about writing new code to emulate something that already exists. Iâm certain I could âeasily addâ reframes features to Fulcro if weâre talking about writing new code. âI can see a full implementation ofâ is rather subjective. That said, I cannot say, for sure, which would direction be âeasierâ to write based on the other as a starting point.
New code is not a problemâŚIâm just saying its a subjective thing to claim you can add the features of A to B more easily that B to A.
I see. The reason I'm most interested in it is that it removes more logic from ui components in an efficient manner. The logic could be removed just by extracting the functions like normal, but then you don't get the advantage of caching and diff/no-diff.
I think youâre claiming that the features of A make adding the features of B easier to it than the other way aroundâŚbut like I said, Iâd rather talk about specifics.
ok, but caching is a non-trivial issue. Cache invalidation is very tricky business. Youâre going to automate that in a distributed system for people, where loading can happen for arbitrary reasons, and the data can change on servers at any time?
It is always put back into the db, correct? as long as the db is the single source of truth, and no subscriptions depend on anything outside of the db, everything should be fine.
Also consider that what youâre talking about is often just an optimization: is the thing really too slow as functions? In my experience, the answer is âusually notâ
so now youâre adding features to a library that require more understanding of the developer, and are possibly harder to trace, in order to optimize somthing that doesnât need optimization
If you had that âfeatureâ, then it might be more palatable to beginners coming from Reframe, and lead to more adoption, which would lead to more contributors, a wider library set, and a better overall ecosystem đ
And Iâm sure there are cases where such a system really would be âbetterâ in some objective ways.
That is a benefit. Let me think about it for a bit. I think I have a pretty firm grasp on Fulcro at this point. I'm super interested in how re-frame works, but maybe what you are saying is true - most of the case where I feel a need for it are actually already addressed.
Iâd be really interested in your take on that. It is probably the best example of exactly this kind of concern
If you were trying to solve a âreal problemâ, making something that makes the code of that objectively better would be a great litmus test
It uses a UISM to manage the logic. I think it is a place where the concepts of Reframe might really lead to a better result.
I'll take a look. And does the current version of the rad demo use all of this so I have a usage example?
ignore the chartsâŚor not. They are just multiple views of the same data. They donât really have anything to do with the logic of interest.
BUT, the fact that they need to transform some of the data a bit more might actually be of interest
againâŚsome code cleanup with functions would be fine, and would be fast enough. But I am very interested in what you might come up with.
I happen to think that website development is also complicated, and that fulcro is close to the actual complication of a complete solution. Most people who don't use it will end up with an ad-hoc system as complicated as fulcro
But, I'm concerned with seeing what can be simplified from a mental model without loss of generality.
âtoo complicatedââŚI think perhaps you mean âtoo hard for the beginner?â The model is actually very very simple. But as you say: the central problem is not trivial and has inherent complexity. Fulcro is trying to be âminimally complexââŚ.and youâre right, Iâd love to see more additions that can remove any incidental complexity that it still has.
At the moment, my biggest pain points using it are Clojure(script) more than Fulcro. Iâve been working on some static analysis tools, but I donât have time to develop the solution. I have some ideas that I think could really help.
Pretty much. I took a solid 1.5 years to learn fulcro to a point where I was happy to start. On and off mind you, but this was spare time learning.
Maybe what is need is a slight update to the material. Part of the complication is the sheer size of the fulcro documentation. I printed it out - runs to 100+ pages. Also, the library itself is huge. It reminds me of the clojure core library - every few days I find something else that is super useful that I never saw before. If I consider the possibility that the major problem with fulcro is not the model, but the small community, I think we could do alot to solve that problem.
(super speculative) Split the docs into 3 parts. a: happy path, simple usage of every part. b: detailed path - more detailed than even the current docs. I've seen many gaps in the current explanations. c: fulcro docstrings. Oddly missing in some spots - I'll look to see what is missing later.
Maybe bring everything into sperate libraries. Core should include ui and mutations, not much else. Add additional libraries for routing, fsm, network, forms... I don't have any idea if this is very useful, but my intuition is that splitting everything into smaller chunks would be a large help.
I want to create a custom form body in RAD, how do I link the form fields back to the attributes? And how do I tell RAD where to insert subforms?
I guess just look at what the default impl does?
Yea it passes the data map around like three libraries, taking it apart and putting it back together until you lose track
See form-state in the Fulcro book. The generated form is exactly what youâd hand-code there.
Then use the pre-supplied functions in rad-`form` ns to say when fields change, save, undo, etc.
If you use person/name
as a field, then there will be :person/name
in props.
this factory in the SUI code is the generic expression of what youâd do to make an input that is fully-functional with respect to settings:
https://github.com/fulcrologic/fulcro-rad-semantic-ui/blob/develop/src/main/com/fulcrologic/rad/rendering/semantic_ui/field.cljc#L19
but more simply:
(dom/input {:value (:person/name props)
:onChange (fn [evt] (form/input-changed! {:form-instance this} :person/name (evt/target-value evt))})
Ahh that helps! I initially already tried to use the functions inside the form/ namespace, but that errored out for me. Turns out I have to put this
inside a map with specific prefixes.
Ooh it failed because I tried to set the password field... I was wondering why on earth that'd fail in my own form and not in the autogenerated one
Is it btw possible to embed a form as a component? I mean I can embed it, but I think I have to call form/start-form!
, although I have not yet figured out what exactly this needs as arguments to function
You mean not as a router target? With reports it is possible, I just need to call a similar start fn so I assume the same applies to the form
What is unclear about the arguments? The docs seem quite clear to me...
timbre_support.cljs:80 ERROR [com.fulcrologic.rad.form:659] - dr/target-ready! was called but there was no router waiting for the target listed: [:vendor/id âŚâid=#uuid "343b0353-cb69-4628-aaf2-820d848f68bd"__hash=-1541908784â˘IEquivIHashIPrintWithWriterjsObject#fulcro/tempid["#uuid "343b0353-cb69-4628-aaf2-820d848f68bd""]TempId]meta This could mean you sent one ident, and indicated ready on another.
Look into the DB for what routers have a pending path, compare
Okay, I have the DB open in Fulcro Inspect ("DB Explorer"). Where do I find pending paths?
It makes sense btw that there is no "pending path", because I don't route to that form. I have that form created like this:
(defsc VendorRegistration [this props]
{:query []
:ident (fn [] [:component/id ::VendorRegistration])
:route-segment ["vendor-registration"]}
#?(:cljs
(do
#_(dom/div
(dom/a {:href "#"
:onClick #(form/create! (comp/any->app this) VendorRegistrationRADForm)}
"Start form"))
(let [tid (tempid/tempid)
regform ((comp/computed-factory VendorRegistrationRADForm {:keyfn :vendor/id}) {:vendor/id tid})]
(form/start-form! (comp/any->app this) tid VendorRegistrationRADForm)
(dom/div regform)))))
I also tried calling form/start-form!
first, and only create the form after, but that gave the same result.
Hm, right. Does start-form trigger dr/target-ready? If not, who does? Go not to the DB but the next tab, DB something, search it for "pending" (or current-route")
could be a bug in start-form. I donât use it without the routing. open to a PR if you find an issue, but no time to debug myself.
Yes, it triggers dr/target-ready?, though not directly, it is called in the state machine
a target ready should not hurt anything, other than showing a warningin the console (that it was unexpected)
Hmm... it runs asynchronously, right? Is there a way to wait until the UISM is in a specific state?
Okay it seems to initialize eventually as soon as I do something in the form that triggers anything like a form/input-changed!
I just... the more I dig in that, the more awful it gets. I tried to switch around the start-form!
and actual element creation, I tried creating the values and give it to the form itself, I tried having a go loop that waits until the state changes to then set my values. It. all. fails. What else can I try, @tony.kay ?
the routing will-enter is the only thing that RAD itself triggers to start the form logic, so if youâre doing that bit the same way (or just using routing) then the logic should be fine.
I'm trying to have it add a form child, and set a ui/ variable, but that'll just error out when I place it in the form body and use form/start-form!
. It works fine with form/create!
.
from there, the SUI RAD plugin can be used for reference on what to do when rendering. I know it is a bit tough to trace because the controls are in a map, but it obviously works with mechanical generation, so all you have to do for manual creation is follow the patterns in there. Sorry there are not docs yet
add a form child? Well, you still ahve to configure that, and you have to start the form machine. If you want to add one on entry, then that is a little more complex, since the machine is responsible for the initialization
If youâre trying to do something that complex you are pretty much just writing a new component, and might as well just do it in pure Fulcro land: youâre controlling the rendering and logicâŚyou can still use the load/save mechanisms of rad.
I see in Fulcro Inspect that the editing state gets activated, but that happens asynchronously, and I can't figure out a way to tell it "hey, run this code after the state machine has entered :state/editing"
There is a ::form/machine
option that will let you plug in your own (derived) state machine. a sm def is just a map, see UISM docs. Replace the startup with your own logic.
Also remember: RAD is meant to be fast to stand up well-known patterns, not solve all problems. It is also meant to be escaped from when it does not address your case well. In this case, the state machine replacement escape hatch is appropriate. In others it might be just to write your own Fulcro component (which can still leverage the load/save, or even some of the rendering logic).