Fork me on GitHub
Mr. Savy00:09:53

ok cool, thank you! what I'm having trouble with then is how make sense of building components together. I'm used to building components that match an html structure so I can build them into one another. for example, if I want a wrapper component around any images blocks I create. fulcro doesn't seem to have the same design philosophy. I think i just need to keep rereading the book though until get familiar enough with thinking in terms of data structures.


you can certainly create a component around image blocks..nothing stopping you, and with Pathom you can easily make virtual edges and fold things together to match the shape of the UI. That’s the beauty of the pair: Fulcro lets you lay it out in the way that makes the most sense for a UI data shape, and Pathom lets you write back-end data resolution that can adapt to those shapes.

Mr. Savy01:09:30

I haven't touched pathom much yet since I'm still getting used to building static data on the page. In this case I haven't yet made sense of how to make components reusable. For example, if I wanted that image wrapper component it looks like I have to define a component for each unique image I use. However, I suspect that's the wrong headspace since that defeats the motivation for making the component in the first place. I'm still pretty novice though. Maybe I could treat the href as the data and pass that in? I'm not really sure. hmm, maybe checking out pathom will help.

Chris O’Donnell03:09:08

You definitely don't need to write a separate component for each image. You should be able to pass in the image source via props just as you would in a vanilla react app. It just happens that component props are derived from query and ident if the component has them. If you're looking to capture a snippet of html/css for reuse, you can always use a component without ident/query or a plain function.

Chris O’Donnell03:09:36

Perhaps we could better understand your concern if you shared a small example where you feel you need to write a lot of different components?

Mr. Savy03:09:05

hmm, I may post some stuff tomorrow when I have more time. I will try. I think the biggest use case is css. For instance, I have a set of unique items (images, links, etc.) and I want to make a component that I can wrap each item in when I display it on the page so they all look the same. Pragmatically speaking I could just do it in a function, but my motivation here is to try build my components using a fulcro flow since i'm trying to learn the framework.


I gave report system in RAD a fair shake and here’s a couple of limits I’ve hit: • it does not support computed columns ::attr/computed-value, so when I wanted to display amount-cents and currency attributes as a single column 30,00 eur , I made up a column with no value with ro/field-formatter that creates the value from other two columns, added it to the report, added amount-cents and currenct to row-query-inclusion . This worked but it’s really brittle. Computed columns should probably be supported, also attributes that are computed should probably be able to declare data dependencies as addition query. • it does not support specifying sort function for the attribute. So when you have strings like “1188 eur per year” and “99 eur per month” the default string sort isn’t that helpful. • I tried to make a report with 15 columns and the table went out of its container. I fixed it in dev tools by adding style “overflow: auto” to div at , but I see no easy way to get that into the app. It seems that it’s hard to customize styles, and it could be beneficial to add a class like fulcro-report-table to that div and to add similar classes to components rendered by that renderer, to enable customization. The other solution would be for me to copy-paste all that rad-semantic-ui code and make my own renderer. • it seems not possible to hide columns dynamically. If I have a control “Show active accounts only” on accounts report, when it’s not selected, I want to show all accounts and “Active” column, which specifies the status. But if that control is selected, then I’d like to hide column “Active” since all the rows I’m showing have active=true, which makes the column just noise.


@roklenarcic You’re expecting a “kitchen sink experience”, which is not what I’m providing. I’m providing a design that is extensible to meet your needs in a well-structured manner. This is an open source effort with a core structure, and everything can be escaped from. The out-of-the box experience is what I’ve needed so far. You want more: • You can write your own plugins for any element of rendering, and support it with your own nsed kws. • You can write resolvers to compute columns, or do the prior item • Sorting: You can define a way to compare rows. Sorting behavior is customizable already • Hide cols dynamically: yeah, that one just isn’t written yet, but is trivial to add…and is trivial for you to also control/add in your own rendering extension So, from my perspective “fair shake” implies that you find it “lacking”, when in fact from my perspective every single item you’re mentioning is a “fixable-by-design” issue due to your own needs.

❤️ 9

Instead of expecting any element of RAD to work the way you “wish it would already”, see it as a framework in which you can dramatically reduce boilerplate. yes, that may mean coding some of the “features” you’d like yourself.


but then you only have to write them once for your 100's of forms and reports


yeah some of these things are solvable in the rendering, I can copy-paste your renderer and augment it. Some other seem more core to the concept, like computed columns for reports (that one would require support in the report system itself not the renderer). I know you don’t have the time to do everything everyone needs, that would be ridiculous. I am just listing some of the first things I’ve ran into.


Computed columns can get complex. There are a number of issues around that which need to be solved, since a computed column might in turn want to deal with data that is naturally nested…for example, you might say “I have three line items on this order, so I’d like to be able to query for the line items in this column, but display a total that is computed”. The options are kind of endless. That said: computed colums *are possible with the current design: Add an attribute to your model with whatever type you want the column to have. It doesn’t matter that the server will respond to it with nothing. Add that column to your report. Set the field-formatter for that column. That function will receive the report instance, the row props, etc. You can make up whatever you want for that column.


So, I think that case you’re pointing out is already supported.


What we need is improved docs 😄


I came up with the same solution, but there’s a big caveat. The problem was that as far as fulcro RAD is concerned that attribute had no value and the while the field formatter thing worked, the sort of the column didn’t. The column logic considered all the rows to have the same value (no value).


Ah, well, the row-compare would have to be customized for that, yes


but still doable without RAD changes


I think pathom and/or fulcro are way smarter than me.. I don't understand why they seem to be able to find an edge despite me not specifying it in the resolver. resolver:

::pc/output [:view/entries]
defsc query:
{:view/entries (comp/get-query Entry)}


pathom viz confirms that there are NO edges between view and entry! how does it work?!

👻 3
Björn Ebbinghaus12:09:30

There is really not much to see in your example. 🙂


it's hard to show the absence of something :) I was under the impression that pathom connect would have to understand joins (edges on the graph, as shown in pathom viz), but it turns out fulcro can infer those all by itself


so I can have a graph in pathom viz with entirely discrete clusters and the UI will still connect the dots

Björn Ebbinghaus12:09:50

The graph in pathom viz is what data you can query for with what information. Fulcro normalizes and renders. So you can have this Client DB:

{:entry/id #:entry{:id 42 :data "foo"}
 :view/entries []}
And you query for {:view/entries [:entry/id]} which returns {:view/entries [{:entry/id 42}]} Fulcro merges this and the resulting db is:
{:entry/id #:entry{:id 42 :data "foo"}
 :view/entries [[:entry/id 42]]}
Your component with query {:view/entries (comp/get-query Entry)} now can render "foo" . I think this is your situation?

Björn Ebbinghaus12:09:28

Hmm.. What do you return in the resolver with ::pc/output [:view/entries] ?


yup, that looks exactly right: {:view/entries [{:entry/id 42}]}


and then there's a separate entry resolver for {:entry/id 42 :entry/food "fish" ...} which gets picked up magically


well, it's maybe not that magical since I asked fulcro to join it explicitly with (comp/get-query Entry)

Björn Ebbinghaus14:09:52

The output of one resolver can be used as the input for another resolver. But in your case you didn’t specify that your resolver provides :entry/id . I would have guessed that Pathom can only use your single entry resolver if it knows that it is reachable beforehand.


it looks like fulcro can infer that edge through normalization? is it good design to rely on that and omit it from the resolver signature?