This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-05-16
Channels
- # announcements (1)
- # babashka (13)
- # beginners (33)
- # calva (26)
- # cherry (33)
- # clerk (5)
- # clj-kondo (3)
- # clojure (40)
- # clojure-europe (24)
- # clojure-finland (2)
- # clojure-norway (29)
- # clojurescript (18)
- # cursive (2)
- # datomic (6)
- # docker (11)
- # emacs (12)
- # events (1)
- # fulcro (71)
- # graalvm (8)
- # hyperfiddle (2)
- # lsp (23)
- # meander (5)
- # off-topic (36)
- # polylith (4)
- # re-frame (6)
- # reitit (13)
- # shadow-cljs (87)
- # spacemacs (1)
- # tools-deps (19)
- # vim (5)
- # xtdb (57)
Hello, I’m very interested in Fulcro. Is it possible to create a custom renderer which uses htmx and its dynamic templates?
Is there some documentation or example on this topic?
I’m not sure what the advantage would be. Are you talking about transpiling https://htmx.org/ this kind of stuff and trying to use Fulcro with it?
The whole purpose of Fulcro is to eliminate that kind of entanglement. If you like what htmx does, then use htmx. The answer to your question of “can I make a custom renderer to do X”? The answer is almost certainly yes, but the follow-on question is “Should I?“, to which, in this case, I would probably answer no. As far as examples: There are youtube videos showing custom rendering with Reagent/Reframe. There are docstrings in the code. There is the code itself. The rendering of Fulcro is somewhat tied to react, but you can use it in a headless mode as well. So, if you just want data management you could use it headless, and add a listener to the atom or a hook in the transaction processing to trigger whatever visualization refresh you want.
Thanks for the indepth explanation. I know you are made Fulcro for non trivial web apps. The idea of the EQL queries and the state machine is really interesting so I want to make use of these in general. But sometimes I have a view which is rather simple and another which is more complex. For the simple one I don't want to have to send and evaluate lots of code on the client.
Hello all. I'm trying to understand routing in Fulcro. I'm at a point I need to phone a friend. Using fulcro inspect, I see that the db has the data for :all-recipes as well as the normalized values. Issue is I can't seem to figure out how to get the all-recipes
key to pull the data from the db and display the list. Any ideas?
Here's the overview of what's going on: https://www.loom.com/share/d50483ce66cb40509cdf9fcb2eb750af
The code:
Routers in Fulcro are dynamic components that have to be told what to do. The “default” view of the initial frame is a pure rendering of state. The routing system hasn’t been started until you actually start it (by routing to a leaf target).
In general I recommend setting up the app to have an initial screen that shows “loading” while you initialize things, and then once you’re running issue a routing instruction to go to the place of interest. That action is what triggers things like will-enter
.
Thanks @U0CKQ19AQ - I have the call to (dr/change-route! main-app ["main"])
So I see the route load, I even see the loading state then the component load. I see the data in the db, but I think I'm not yet fully understanding how query, ident, and initial-state work. Somehow I see all the normalized data and top level root data all-recipes
but it doesn't render. Going back through all the videos.
Thanks for the response.
:target [:component/id ::main :all-recipes]
otherwise load doesn’t know where in the graph to put the loaded data, and just defaults to putting it in app root
the beauty of having normalized data is that targeting is always either at the root, or at some field in a normalized entity (so either you don’t need to say it, or it is a 3-tuple of ident + field)
so:
#(df/load app
:all-recipes Recipe
:target [:component/id ::main :all-recipes]
:post-mutation `dr/target-ready
:post-mutation-params
{:target [:component/id ::main]})
Unfortunately no, getting some other errors:
[com.fulcrologic.fulcro.routing.dynamic-routing:137] - route-deferred was invoked with the ident [:component/id :com.sajb.ui/main] which doesn't seem to match the ident of the wrapping component (class function (js_props){
var this$ = this;
(defsc Main [this {:as props
:keys [all-recipes]}]
{:ident :all-recipes
:query [{:all-recipes (comp/get-query Recipe)}]
:initial-state {:all-recipes [{:recipes/id 1
:recipes/name "Blueberry Jam"}]}
:route-segment ["main"]
:will-enter (fn [app route-params]
(dr/route-deferred [:component/id ::main]
#(df/load app
:all-recipes Recipe
:target [:component/id ::main :all-recipes]
:post-mutation `dr/target-ready
:post-mutation-params
{:target [:component/id ::main]})))}
(tap> {:all-recipes all-recipes})
(d/div "All Recipes"
(when all-recipes
(d/ol
(mapv ui-recipe all-recipes)))))
I got a lot of reading to do :rolling_on_the_floor_laughing: I feel like I understand the high-level but really don't have a good grasp of the specifics
That is the main hurdle to understanding I/O in Fulcro. Loads (and mutation return values) have to be targeted unless all you care about is the normalized data.
When you load, you’ll always get the normalized data, as long as your resolver returns it with the right shape. But, if you want to join that loaded data into your UI graph you have to tell it “where”
so I could write a full-stack mutation like “gen-recipe” that returns a Recipe. I could then write a mutation with:
(defmutation gen-recipe [_]
(remote [env] (m/returning env Recipe)))
and if I transact that (and the server actually returns a Recipe), then that recipe is now in my db. BUT it is not on the UI anywhereI see, I think the thing I'm struggling with is that I look at the local db, and I was thinking - that is the ultimate source of rendered truth, that somehow when that updates, all queries will always rerender. Am I misunderstanding though?
you can include a link query if you want to read root keys, but I don’t recommend that in a case like this
You can also do this: https://book.fulcrologic.com/#_link_queries but be sure to read the warnings (and use sparingly…this isn’t how it is intended to be done most of the time)
If you have some master list that should be shared all over the place, then putting it in root and using a link query is what you should do
otherwise if I have a top level nav. Recipes | Settings | Account and recipes first displays a master list of all recipes, and then selecting one opens details. In this flow, would top level :root/all-recipes be the goal? Or targeting is better?
:query [{[:root/all '_] (comp/get-query Recipe)}]
but again be sure to read the warnings..you must have initial state or that won’t work
haha ok. I'm going to dig back into the docs and vids. Really appreciate the lesson Tony. Thanks again for the amazing work
I personally would localize the data to a component. That would let me do things like play with pagination and incremetal loadings, etc.
@aramz perhaps https://blog.jakubholy.net/2020/troubleshooting-fulcro/ can help the next time you run into troubles?
The general idea in Fulcro is that rendering is as close to a pure function of state as possible. I/O is always triggered by some kind of action (user event, explicit call on startup, timeout, etc.)
I realize that because the router renders the route that this may be confusing: but rendering is just showing what you initialized the app to be.
@aramz perhaps https://blog.jakubholy.net/2020/troubleshooting-fulcro/ can help the next time you run into troubles?