Fork me on GitHub

I modified load-field! today (v 3.1.10 released). It is 100% bw compat, but now can accept a vector of fields: (df/load-field! this [:a :b]) which it will focus the query to. The reason for this change is I realized :pre-merge will not work properly if you just load one field and not the ID (since it won’t find current-normalized if the ID isn’t available). So, if you’re using load-field! on a component that uses pre-merge you should remember to add your ID field to what you want to load. This also makes it more useful if there are multiple things you want to incrementally load. Book updated.

🎉 20

is having a state machine active necessary for dynamic routing?


i'm trying to setup a minimal fulcro project based on template, but haven't been able to get routing working without api / state machine logic. for example, seeing this warning in logs

DEBUG [com.fulcrologic.fulcro.ui-state-machines:?] -  Attempt to get an ASM path [:com.fulcrologic.fulcro.ui-state-machines/local-storage :pending-path-segment] for a state machine that is not in Fulcro state. ASM ID:  :


dynamic routing uses state machines behind the scenes, but it’s nothing you have to concern yourself with. That error looks like you forgot to call dr/initialize! during your app startup, which is where Fulcro sets up the state machines it uses.


right. You have to compose in initial state and initialize it either by calling change-route or initialize.


There’s probably something I could do to make that automatic…probably should look into that


so I was calling initialize! but looks like you also have to call change-route and set an initial route? I figured / would be the default reason I commented out the change-route function in init handler is because I was seeing this warning: UNEXPECTED EVENT: Did not find a way to handle event :timeout! in the current active state: :routed


routing is working but also seeing this error in console Attempt to get an ASM path [:com.fulcrologic.fulcro.ui-state-machines/local-storage :pending-path-segment] for a state machine that is not in Fulcro state.


@alidcastano So, the latter warning can possibly happen from startup sequence, and is usually harmless. There is no “/” route, just like in apache/nginx/ring: there is no “file” at “/”. Think of the dynamic router as the base layer. It might be used by react native or web or whatever. In web tech you typically say “/” really means “/index.html”…But that is an explicit internal or external redirect…you have to map it. No different here. So, dyn router is the means by which you can put things on screen, but controlling the routes is up to you. Thus, if your URL says “/” you need to translate that to what real resource that means (which will have a concrete name/path).


And yes: dyn router currently is a little noisy with warnings in the console that I have simply not had time to look at…I’m using it heavily (as are others) in production products and it works…but I really need to make the time to fix the warnings. Sorry.


I would love for someone to layer web stuff (as an add-on) on top of dyn router (or use the lessons learned and make something more)…but Fulcro isn’t meant to be web-only, so neither is dyn router.


np at all, just wanted to make sure I set my project up correctly. Thanks for clarifying about warnings it definitely makes sense to make the router platform agnostic. I was just confused because, at least from my reading of docs, it couldn't find mention of that and since Fulcro has DOM elements built in I assumed web routing would have dom support too. but it was clarified in another thread that you go over this in one of the tutorial videos


I’m having some trouble working with #fulcro/tempid["…."] literals in the REPL. I’m curious what you do to make this work? I tried setting tempid/tempid as the reader in data-readers but that doesn’t quite do it It worked to set my own fn as the data reader:

(defn readTempID [form]
  (com.fulcrologic.fulcro.algorithms.tempid/tempid (first form)))
(set! *data-readers* (assoc *data-readers* 'fulcro/tempid #'user/readTempID))


right, tempids are integrated into the transit stack, but we don’t have them in data_readers.clj


at the REPL I just call the tempid function, but I can see if you’re copy/pasting…


yeah I’m copying a big thing of form diff data to work on my server-side save-form fn. I looked at the RAD version but it doesn’t quite handle my case. I got some inspiration from it though like (sp/select (sp/walker tempid/tempid?) form-delta)! I must say I’m impressed with the tempid resolution. It’s amazing to watch a whole nested slew of things in inspect change from tempids to regular ones!


do most people navigate by . passing route-segments (`(dr/change-route this ["path"])` or components (`(dr/change-route this (dr/path-to Comp)`)? ideally I wanted to only do latter so that there could be one source of truth about which routes exist, but realized I'd be running into cyclic dependencies... so navigating via components doesn't seem to really work too often in practice?


@alidcastano You can avoid cyclic dependencies, for example:

(gen/registry-key->class `ui.entry/Context)
, where that function is:
(defn registry-key->class [cls-key]
  (if-let [cls (comp/registry-key->class cls-key)]
    (dev/err "Not found in registry" cls-key)))


great to know there's a workaround - thanks for the example. will try this out now 🙂


works wonderfully, thanks again 🙌

fulcro 4

and you can use keywords…no need for syms


what's the keyword equivalent of, say, ui.entry/Context



👍 4

So in your example instead of Comp you would have (gen/registry-key->class `Comp)


does fulcro's browser router not use the url as the source of truth? running into situation where I end up in route that doesn't match url path, and also, i try to navigate via component (as discussed above) and it says i'm already in the given path (even though I'm not)


The fulcro router is completely separate from the URL. It’s up to you how to connect the two


In one of the fulcro3 videos Tony shows one way to connect the two


ah well that explains it 😅


is this in docs at all?


how to connect them? I’m not sure, I’d look under the dynamic routers section


I’ve used the pushy and reitit libraries for good effect.


This is what I do, based on that video:

(defonce history
    (fn [p]
      (let [r-segments (vec (rest (str/split p "/")))]
        (timbre/spy :info r-segments)
        (if (seq r-segments)
          (dr/change-route SPA r-segments)
          (dr/change-route SPA ["main"])))) identity))

(defn start! []
  (pushy/start! history))

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


yeah can't find anything in docs, but thanks for the code snippet, will start there


might be worth adding that to the docs

👍 4

Another idea for RAD that would be particularly handy for the mobile crowd: Offline mode support. I think the combo of a CLJC declared data model and Fulcro database format (with form-state’s dirty diff algorithm) could be used to make a nearly automatic offline mode, where you simply say “go offline” and RAD records into local storage the current db as “start”, and then at each tx updates an “end” snapshot. Then the “save” to get the server up-to-date is basically the form diff of the two, based on known persistent declared attributes.

🔥 16

This is something I still need to address better in my app, so I may pick your brain on this more in the near future. Once I have a working concrete implementation, it would be easy to add to RAD. One thing that complicates it a bit is that mobile connections can be very flakey, and it’s easy to end up in situations where the app is rapidly fluttering between online/offline state. Some kind of debounce and other logic will be needed to, for example, determine when a connection has been stable long enough to really consider the app to be online and attempt network requests.


well, you just don’t say you’re in online mode until a commit of offline changes is complete


This would have solved a major feature request for an internal product I'd worked on a couple of years ago. Before I'd heard of fulcro. I'd been nudging the scala and angular js project toward this direction


before the whole project was put on ice to be rewritten in some vendor solution, before they eventually realised that wouldn't work and that was axed. 😄


The other thing that is probably more easily amenable to general apps is to just recort the abstract sequence of remote ops (mutations) that are needed to send when back online. Reading is also a problem…have to pre-read things before going offline. I mean true transparent offline mode prob needs quite a bit of addl work.


There is some conflict management to consider, but for certain classes of apps (i.e. ones that mainly create new data) this could work very well without even considering conflicts.


and something like 90% of the code to do it already exists ;)


argh…not enough hours in the day 😜

parrot 4

where are the fulcro docs hosted? found the fulcro-developers-guide but repo seems to be only host the code examples and fulcro/docs seems to only host the website code


the former has an adoc file in the root of the repo


oh haha, didn't consider it'd all be in a single file. 😅 must make it easy to edit


yeah, just don’t use preview mode in IntelliJ’s plugin while editing.