Fork me on GitHub

Is there an idiomatic way to dealing with change of uism states when the browser back button is clicked. I have a uism managing a flow of components. Each state in the uism is a step in the flow. If the user hits the browser back key to move back to a previous component the state in the uism isn’t updated.


Is there a nice way to do this? Do I need to hook into the html5history somehow? I’m using RADs implementation.


I could trigger an event in each component’s componentDidMount, to activate the right state, but that means having a handler in every state in my uism.


I’ve proceeded with the last option. If anyone has a better solution please let me know.

Jakub Holý (HolyJak)13:08:31

To me, html5 history seems the natural place, provided you also update the url as the user goes through the flow. Just catch it and issue the appropriate uism event.


has anyone run into issues getting the pathom index explorer working with rad + the datomic adapter? to my eye, the resolvers created by datomic/generate-resolvers are wrapped in such a way that throw on an attempt to serialize into transit. an e.g. of what a I’m seeing in the env of my parser:

    {:com.wsscode.pathom.connect/sym dispatch/id-resolver,
     :com.wsscode.pathom.connect/input #{:dispatch/id},
     {:dispatch/status {}},
     :com.wsscode.pathom.connect/batch? true,
     #object[com.fulcrologic.rad.database_adapters.datomic$id_resolver$with_resolve_sym__46767$fn__46768 0x76d8af97 "com.fulcrologic.rad.database_adapters.datomic$id_resolver$with_resolve_sym__46767$fn__46768@76d8af97"]}}


I have the by-the-book transit and api-handler middleware installed

Jakub Holý (HolyJak)16:08:05

I fixed something like that before. Look at how the index is exposed and add some more exclusions to it?

Jakub Holý (HolyJak)16:08:53

Resolvers are functions and thus not serializable => must be excluded


thank you! did not know about transduce-maps – you learn something new every day


I don't know if this is a Fulcro or Pathom question. (Or both?) Please let me know if I should post this elsewhere. Let's say I have a Pathom resolver that takes a :document/id as input, and outputs a bunch of things about the document, e.g. :document/title, :document/size, etc. And I have Fulcro component A that has the :document/title and :document/author in its props. Clicking a button in component A causes component A to render another component B that has the :document/size and :document/mime-type in its props. Something like:

(defsc ComponentB
  [_ {:keys [drawing/size drawing/mime-type]}]
  {:query [:drawing/id :drawing/size :drawing/mime-type]
   :ident :drawing/id}
  (dom/div ...))

(def ui-component-b (factory ComponentB {:keyfn :drawing/id}))

(defsc ComponentA
  [_ {:keys [drawing/title drawing/author drawing/component-b]}]
  {:query [:drawing/id :drawing/title :drawing/author :drawing/component-b (get-query ComponentB)]
   :ident :drawing/id}
  (dom/div ...
           (ui-component-b component-b)))
Everything about the document is returned by one Pathom resolver that takes the document/id as input and returns everything else. However, Fulcro sends a query that looks like: [:drawing/id ... {:drawing/component-b [:drawing/id :drawing/size :drawing/mime-type}] The response is :drawing/component-b nil because there isn't a Pathom resolver associated with this input. I'm hoping I can create components that are views of subsets of the data of a single database object without embedding the structure of the ui layout in the backend database resolver. How can I make either Fulcro or Pathom treat a query for {:drawing/component-b [:drawing/id ...]} as though the query was [:drawing/id ...]? FYI, Component A is routable and includes a :will-enter hook. Component B is not routable and does not have a :will-enter hook. Thanks


I think my options are or I couldn't get link queries to work, and I haven't tried to create shared resolvers, yet


I think you want a placeholder? {:>/component-b (comp/get-query ComponentB)}


basically it's a hint to pathom to treat it as a "flat" join, staying at the parent to fetch that data instead of trying to join elsewhere


Trying now. Thanks!


This appears to be working. Thanks @U797MAJ8M!

👍 3

I would have a component that is just for use when loading/merging, that has all the attributes. i.e. make sure the query that Fulcro sends is from the non-UI component. Eventually you will have quite a few of these non-UI components.

👍 3
Jakub Holý (HolyJak)11:08:52

In this case he can achieve what he needs using placeholders. No need to duplicate the query - and maintain those in sync! - into a non-UI component. No?


Is it worth avoiding 'query components'? In fact I'm thinking that a bigger Fulcro code-base will just about only query with query components. Also a simpler concept than placeholders. In your front-end there will be components that are UI facing and those that are back-end facing, reflecting the fact that BE and FE entities are different.

Jakub Holý (HolyJak)18:08:37

It is evil because now the info about what data a component needs is at two places: its own query and in the query component - and you have to maintain those in sync. Exactly the problem Fulcro's co-location of component body and :query solves and one I hate from REST. YMMV.


I'd be interested to know of any larger projects that don't have query components. To see if your 'non-evil' vision can be realised! @U0CKQ19AQ might know. If such a thing does exist then that's certainly interesting.


I rarely use query components that aren’t somehow tied to the UI. Placeholders are nice for this sort of fan-out of concerns. Fulcro’s facilities are designed so that you can get a limited set of info on loads if that is your concern (e.g. with focus/without options of load) and incrementally load things from there. If a UI component ever needs that particular data, then it should be in the query. Controlling the load is in the logic, and need not vary the UI query. The UI code can be written to be aware that some thing might not be available “right now”. If the UI component never needs a particular thing, then usually you don’t need to load it. This is why things like form-state deal in deltas instead of absolutes: you only want to care about what was worked on in the UI, not what the server knows about. This is also the point of things like RAD save middleware: sometimes the UI sends a new thing that is incomplete, and there needs to be server logic that understands the pattern of filling out the rest. It is true that sometimes you want to load data that is never used by the UI at all (perhaps some algorithmic parameters, session info, etc.). That is the primary case for query components (or these days just using (raw-components/nc) ). But those are cases where the data doesn’t really end up in the UI at all. It’s all meant to be flexible to meet whatever need you have, but I do not really recommend using query components as the way in which you feed your UI. I agree with @U0522TWDA there: seems like incidental complexity.


In my experience sometimes the same entity has different representations in the UI, with each component query missing some of the entity's attributes. And here I'm thinking about data that is not changed by other people so only needs to be loaded once. Likely near the beginning of the user's use of the application. Each UI component will use the data that was loaded by the query component. So I wasn't thinking about the case where loading is always done when the user navigates to that screen. If that was always the situation query components for UI data loading would indeed be pointless. ('always loading' like this is RAD Forms point of view). I still think query components can be used to feed your UI - where the data coming in will not be changed by anyone else, and you want to look at it from more than one UI component. Some applications will have a lot of this (includes historical RO data, such as accounting data), and I guess that's what's informing my opinion here.