fulcro

Book: http://book.fulcrologic.com, Community Resources: https://fulcro-community.github.io/, RAD book at http://book.fulcrologic.com/RAD.html
2021-04-09T09:10:11.442700Z

I've been testing out the fulcro 3.5 raw react stuff, and thanks to hooks (not fulcro raw per se) my components do end up having a lot of lifecycle (react/useEffect ..) stuff that I'd like to abstract away properly some time (probably with more uism). But integrating fulcro with react hooks is really nice to me. I've done an autocomplete recently that uses a union query on the matches. And material-ui useAutocomplete does a bunch of the logic. It's better because earlier I was using :use-hooks? and that wouldn't work as nicely when re-rendering a new hook as I'd need a page refresh.

Mark Thomas 2021-04-09T09:20:21.448600Z

I’m enjoying playing around with Fulcro RAD. I’ve been able to get something up and running with forms and reports really quickly (and as a relative Clojure newbie!) Out of paranoia, I’m interested in enforcing attribute and form validations in the save-form mutator to guard against malicious network requests. Am I thinking about this the right way or would another step in the save middleware (used by form/pathom-plugin) be a better way to do this?

thosmos 2021-04-09T17:54:25.452Z

I have a basic RAD report with a :bigdec and a couple of :ref attributes. Is there a way to pull a display field for the refs and format the bigdec without making a custom row component? Here’s what a row looks like at the moment:

{:db/id "17592186557961"}	[TaggedValue: f, 3]	string_value	{:db/id "17592186557686"}

tvaughan 2021-04-09T18:23:32.455400Z

I've recently started to see an error. Fulcro and other dependencies have been updated recently (last updated more than a month ago). I can't think of any relevant changes to the source code that may have caused it. Certainly the component in the error message hasn't changed. The error is: > ERROR [com.fulcrologic.fulcro.components:874] - Props passed to http://ns.path.to/ComponentName are of the type function Any hints where I should start to look? This happens when I click on a link that triggers a route change. Thanks

Jakub Holý 2021-04-11T08:59:35.487200Z

@tvaughan after this https://github.com/fulcrologic/fulcro/pull/472 you hopefully get a better error msg

👏 1
tony.kay 2021-04-09T18:51:16.455900Z

Thanks for the feedback. The autocomplete kinds of cases are definitely the ones where I see the clearest improvements. Other cases might make as much mess as they clean up, but this use-case seems pretty much just a win.

tony.kay 2021-04-09T18:53:50.456100Z

of course you should do that. Save middleware is where you put that logic. RAD cannot write that for you because it does not know anything about your security concerns (how you model permissions/ownership) nor do I personally plan to write a general system for everyone. If you model an ownership system where each entity can be easily checked (e.g. a field on every entity that points to the owner), then a simple permission check in the save middleware is basically this: For each ident in the form diff (each entity to save): Pull the ownership field and check against session. If any fail, deny the save.

tony.kay 2021-04-09T18:56:51.456300Z

make a virtual attribute that represents the label (and can resolve it with input of the row id -> ::pc/resolve on the back-end). Then just add that virtual attribute as a column on the table.

tony.kay 2021-04-09T18:57:55.456500Z

We updated Fulcro to try to improve the error messages it gives. Does that one give you a stack trace? If not, you can set a source breakpoint on the components:874 in js tools in Chrome.

tony.kay 2021-04-09T18:58:17.456700Z

It is possible that the error is mis-detecting something that is OK, and could therefore be a bug in the new error checking. (The errors should not affect behavior…if it was working, it should still work. they are informational)

tony.kay 2021-04-09T18:58:56.457100Z

I’d love to know which it is: problem with your code, or problem with the error check.

Jakub Holý 2021-04-09T19:15:34.458Z

I likely says "of the type function" because to JavaScript, all cljs data structures look like a function. This is the code:

(when-not ((fnil map? {}) (gobj/get props "fulcro$value"))
                    (log/error "Props passed to" (component-name class) "are of the type"
                      (type (gobj/get props "fulcro$value"))
                      "instead of a map. Perhaps you meant to `map` the component over the props?"))
In this case we shall likely print its .constructor.name, if any.

tvaughan 2021-04-09T19:28:04.458500Z

Yes, there is a stacktrace. I've copied it to https://gist.github.com/carrete/f5f2bff186118f408825cfa16f6b8123 It's triggered by the onClick event below:

(defonce ^:private history
  (pushy/pushy
    (fn [path]
      (dr/change-route! app path))
    identity))

(defn route-to!
  [path]
  (pushy/set-token! history path))

:onClick #(route-to! (dr/path-to DrawingUpload))
I've copied and edited the functions above slightly for readabilty. It the path seems wrong, e.g. "/foo/bar" vs. ["foo" "bar"], then I screwed up in my edits

tvaughan 2021-04-09T19:30:17.458800Z

From https://github.com/holyjak/tmp-fulcro-errors/blob/master/appendix-fulcro-errors-and-warnings.adoc#user-content-err-comp-props-not-a-map, The props definitely shouldn't be a list, but I'll look. Thanks

tvaughan 2021-04-09T19:33:51.459100Z

Add to which I'm not calling the factory of the component. I'm not sure where that happens when something is routed to

Jakub Holý 2021-04-09T19:53:40.459300Z

In the body of the problematic component, can you log the props to see what type it has?

Jakub Holý 2021-04-09T19:55:46.459500Z

The "function" has a root and a tail and a count so it looks like a list / vector?

tvaughan 2021-04-09T20:08:14.459700Z

The props is the component's ident, [:componet/id :drawings-upload]. The component is a singleton, but this seems wrong, right?

✅ 1
tvaughan 2021-04-09T20:17:32.460200Z

Here's the top part of the component:

(defsc DrawingUpload
  [this {:keys [drawing/kind
                ui/attachment]
         :as props}]
  {:query [:drawing/kind
           :ui/attachment
           form-state/form-config-join]
   :ident (fn [] [:component/id :drawings-upload])
   :initial-state (fn [_]
                    (form-state/add-form-config DrawingUpload
                                                {:drawing/kind nil
                                                 :ui/attachment nil}))
   :route-segment ["drawings" "upload"]
   :form-fields #{:drawing/kind :ui/attachment}}
  (println props)
  ...)

tvaughan 2021-04-09T20:20:37.460400Z

I also see WARN [com.fulcrologic.fulcro.routing.dynamic-routing:263] - More than one route target matches ("drawings" "upload") which seems impossible. There are only a few components with route segments. All of them unique

tvaughan 2021-04-09T20:25:58.460600Z

As well as ERROR [com.fulcrologic.fulcro.algorithms.form-state:554] - FORM NOT NORMALIZED: [:component/id :drawings-upload] I'm not sure if these are related. The two errors above about props not being a map and duplicate route targets happen when the onClick event is triggered. This error is triggered when form values are changed and set-value! is called

tvaughan 2021-04-09T20:43:30.460900Z

Oh this is bonkers. TGIF! I formatted some things which triggered a rebuild and now props is correct. The duplicate routes and not normalized form errors remain though :face_with_symbols_on_mouth:

tvaughan 2021-04-09T20:47:51.461100Z

Hold on. It's back after a shift+reload in the browser

tvaughan 2021-04-09T21:05:22.461300Z

I don't see the component's ident in :com.fulcrologic.fulcro.algorithms.form-state/forms-by-ident

tvaughan 2021-04-09T21:07:29.461500Z

Nor do I see the component in the denormalized db. However, I do see other singleton's under :component/id

tony.kay 2021-04-09T21:37:07.461700Z

Remember that initial state is a composition to root for the first animation frame drawn on your entire app. If D.U. isn’t composed to root initial state, then you won’t get that form config, and the props for it will start out nil. If you’ve then done other operations to make the thing sorta work, then it is likely you forgot to actually add the form config (because you thought you already had).

tony.kay 2021-04-09T21:38:09.461900Z

Worry less about the details of the warning, and try following the data graph in the DB (e.g. via DB Explorer, where you can click on idents to follow the data tree). If you cannot follow the path from root UI through db to the leaf, then your state is just wrong, and initial state is probably the error.

Tyler Nisonoff 2021-04-09T22:05:41.463900Z

is there a way to use load params / query-params with m/returning? Im trying to keep pagination consistent by ensuring load params always include the pagination parameters, but having trouble getting this working with a mutation using m/returning

Jakub Holý 2021-04-10T17:00:07.470300Z

I don't really follow. m/returning is about what the mutation returns while params are about the (extra) inputs it gets?

tony.kay 2021-04-10T19:27:06.470600Z

m/with-params

tony.kay 2021-04-10T19:27:25.470800Z

but that changes the params of the mutation…

tony.kay 2021-04-10T19:28:13.471900Z

that’s an interesting use-case. It’s just AST manipulation…so you could rewrite the returning bit to include params

Tyler Nisonoff 2021-04-10T19:29:08.473300Z

I was trying that, but my env -> query-params were still showing up as empty... I also tried pulling it from env -> ast -> params but no luck... will try again later today (on phone at the moment)

Tyler Nisonoff 2021-04-10T19:29:42.474400Z

(I tried m/with-params) to be specific Was thinking about a custom ast manipulation, can look into that

tony.kay 2021-04-10T19:30:14.474600Z

so, on the server-side the query params in the env are extracted by a plugin I think, right? Not normal pathom logic.

tony.kay 2021-04-10T19:30:34.475100Z

so, you might have to tweak both sides, since the returning logic is a post-parse from the mutation processing

tony.kay 2021-04-10T19:30:50.475300Z

but as far as adding params to the query itself, I think that should work…give me a sec

tony.kay 2021-04-10T19:47:18.475600Z

Try SHA 2b5dff2e9f34ff6f47a5f1bcc36bc088a14c552d

tony.kay 2021-04-10T19:48:43.475800Z

I added a returning that supports an extra arg for query params, which it will then put on the returning query. You’ll still need to look for them (they’ll be on the first prop of the query AST on the server)…to get them into the env would require a bit more work I think

Tyler Nisonoff 2021-04-11T01:04:47.476300Z

Thanks Tony, will try it out when home!

Tyler Nisonoff 2021-04-12T16:42:35.027200Z

@tony.kay having trouble testing it.. getting:

Syntax error compiling at (com/fulcrologic/fulcro_i18n/i18n.cljc:102:22).
No such var: comp/*shared*
Im using:
com.fulcrologic/fulcro-i18n            {:mvn/version "0.0.5-alpha"}
` And fulcro-rad depends on i18n via
com.fulcrologic.rad.picker-options
it looks like comp/*shared* may have been removed in commit: 292025c1d

Tyler Nisonoff 2021-04-12T16:49:37.027400Z

i think i may just have to update i18n to use rc/*shared* — can try that EDIT: compiling now — testing

tony.kay 2021-04-12T17:22:42.027700Z

bah…I moved that var

tony.kay 2021-04-12T17:22:51.027900Z

that’s a pain

Tyler Nisonoff 2021-04-12T17:37:25.028100Z

no worries, got it working! Heres the query-params logic:

(def query-params-to-env-plugin
  "Adds top-level load params to env, so nested parsing layers can see them."
  {::p/wrap-parser
   (fn [parser]
     (fn [env tx]
       (let [children     (-> tx eql/query->ast :children)
             query-params (reduce
                            (fn [qps {:keys [type params] :as x}]
                              (cond-> qps
                                (and (not= :call type) (seq params)) (merge params)))
                            {}
                            children)
             env          (assoc env :query-params query-params)]
         (parser env tx))))})
I added a conditional to check if the child query is of type call, then recursively check the params on its query, and add that to the env. Not sure if thats the best general-purpose logic, as ideally they’d only show up in the env after the mutation but during the load, but I’ll have to look deeper into pathom’s plugin system to see if thats doable — this works for me at least for now — and if we like it in general i can add a PR

tony.kay 2021-04-12T17:39:56.028300Z

Try this commit for the shared fix: 50f7c0d6dce72d7f55634db84b9acabda1ed5df5

tony.kay 2021-04-12T17:40:38.028500Z

be interested in knowing that that fixes your compile error. I do not intend for 3.5 to break projects

Tyler Nisonoff 2021-04-12T17:43:29.029Z

@tony.kay that fixed it, thanks!

Tyler Nisonoff 2021-04-12T17:44:12.029400Z

after releasing 3.5 i can submit a PR for i18n to update to rc/*shared* if thats still the strategy

tony.kay 2021-04-12T17:44:34.029600Z

no, I moved it back

tony.kay 2021-04-12T17:44:40.029800Z

there was no need to move it after all, which is good

Tyler Nisonoff 2021-04-12T17:44:44.030Z

:thumbsup:

Tyler Nisonoff 2021-04-12T17:49:30.030200Z

if you have thoughts on if adding the query-params from the mutations load to the env in query-params-to-env-plugin is something you’d like merged in, happy to make a PR or work on a better approach — definitely understand if you dont have time to think about it though.

tony.kay 2021-04-12T17:55:57.030400Z

It would be nice to have it. The load primitive of Fulcro always has a single top-level key, so for single loads that plugin is fine (at the parser level), but mutations (as you noted) are not so clear-cut, since more than one can be sent, and as a result each could have its own query params. So, the general solution would have to change the env value based on which mutation was running…but env is immutable, so some possible solutions are: • Merge all of the query params together into one map. Key collision is then possible and undesirable. • Figure out how to rewrite the env after a mutation. I don’t know if @wilkerlucio has any fancy tricks built-in, but you could use wrap-parser to put an atom in the top-level env like :alternate-env (atom nil) and then add a wrap-read and wrap-mutate that pass that as env when it is non-nil. That way a return on a mutation that needs to change query params could do so by resetting the alt env. • Others???

👍 1
tvaughan 2021-04-09T22:08:32.464Z

Thanks @tony.kay. I understand completely. I do understand it's an indication of a serious problem that I can't navigate to the component in the db explorer in the inspector. I am however at a loss to know where to look next. The onClick event and component, minus its dom output, are above and they seem correct to me. Previously form config state was added in the pre-merge hook, but I don't see that being used in the documentation or templates any more. I saw an example of that being added in the initial-state hook so that's where it is now. It's quite possible that I need to make another similar change. There is no factory for this component. It's listed in the site's router and is rendered when it's routed to via the onClick event. This is where my understanding of fulcro goes into hand wavy magical black box territory. Currently my only guides are the error messages above. When I look at how the initial state is setup, my understanding of fulcro isn't deep enough such that the error is obvious. If things look like what's in the documentation or a template then it looks correct to me, even if it isn't. I'll keep digging though. I'll try to create a smaller, reproduction of the problem. That's helped me before when I was in a similar situation. Thanks again

tony.kay 2021-04-09T22:43:52.464300Z

welcome. The magical black box feeling is something you should address first. Get a clear understanding of how Fulcro works…to do any less is to waste a ton of your time. I’d recommend the new grokking Fulcro series if you have already been using it for a while….particularly the state stuff around episode 3a: https://www.youtube.com/watch?v=r1bMQxTr2QA&list=PLVi9lDx-4C_TBRiHfjnjXaK2J3BIUDPnf&index=3&ab_channel=TonyKay

tony.kay 2021-04-09T22:46:43.464700Z

Fulcro is very very simple, but if you make assumptions about how it works and just try to follow examples without understanding the specifics it will be much much harder than other things you’ve used. If you take the opposite approach you’ll benefit a lot more, and I hope you’ll find the understanding it (in a deep way) is very much easier than other systems.

tvaughan 2021-04-09T23:02:34.469900Z

Thanks. I haven’t seen the new video series, yet. I have watched the original series on youtube, read the book, looked through the templates, and lurked on this channel. I’ll review these things as well as watch the new video series. I had forgotten about it. Thanks for the reminder