The implementation of processing load/mutation result graph targeting.
The implementation of processing load/mutation result graph targeting.
The algorithm and support functions for converting a normalized Fulcro database to a tree of denormalized props.
The algorithm and support functions for converting a normalized Fulcro database to a tree of denormalized props.
Some misc. utility functions. These are primarily meant for internal use, and are subject to relocation and removal in the future.
You have been warned. Changes to this ns (or its complete removal) will not be considered breaking changes to the library, and no mention of said changes will even appear in the changelog.
Some misc. utility functions. These are primarily meant for internal use, and are subject to relocation and removal in the future. You have been warned. Changes to this ns (or its complete removal) will not be considered breaking changes to the library, and no mention of said changes will even appear in the changelog.
Functions that assist with supporting form editing/checking/diffing in Fulcro UI. These functions work
by making a pristine copy of your entity, and tracking what fields have been touched. You are responsible
for triggering these various states by marking fields as complete (mark-complete!
), telling it to
copy the data to/from pristine (e.g. entity->pristine
), and by asking for out-of-date data for the current
vs. pristine copy (dirty-fields
).
There is also support for detecting which fields have been marked complete and are dirty.
Validation can be done via Clojure spec (not recommended), or by defining your own field validation functions via
make-validator
(recommended). This general-purpose validation factory function can easily be used to create more
automated validation factories that can be more configuration-driven, but this is left as an exercise for the community.
Specs are not recommended because forms commonly have multi-field dependencies that simply are not well-supported, and sometimes the use of things like Fulcro tempids leads to specs that you'd rather not have on your server. Use of spec really boils down to your intention for those spec (i.e. hard validation of final database value vs. potential runtime look of the data as it is manipulated). Specs that include "state" information will cause you more pain than you want, though you can certainly leverage specs anywhere it makes sense using the validator factory.
IMPORTANT: This namespace is about (possibly recursive) form data management. Rendering and such are not part of the stated intention. See Fulcro RAD for more fully-automated, multi-platform form generation.
See the Developer's Guide for more information.
Functions that assist with supporting form editing/checking/diffing in Fulcro UI. These functions work by making a pristine copy of your entity, and tracking what fields have been touched. You are responsible for triggering these various states by marking fields as complete (`mark-complete!`), telling it to copy the data to/from pristine (e.g. `entity->pristine`), and by asking for out-of-date data for the current vs. pristine copy (`dirty-fields`). There is also support for detecting which fields have been marked complete and are dirty. Validation can be done via Clojure spec (not recommended), or by defining your own field validation functions via `make-validator` (recommended). This general-purpose validation factory function can easily be used to create more automated validation factories that can be more configuration-driven, but this is left as an exercise for the community. Specs are not recommended because forms commonly have multi-field dependencies that simply are not well-supported, and sometimes the use of things like Fulcro tempids leads to specs that you'd rather not have on your server. Use of spec really boils down to your intention for those spec (i.e. hard validation of final database value vs. potential runtime look of the data as it is manipulated). Specs that include "state" information will cause you more pain than you want, though you can certainly leverage specs anywhere it makes sense using the validator factory. IMPORTANT: This namespace is about *(possibly recursive) form data management*. Rendering and such are not part of the stated intention. See Fulcro RAD for more fully-automated, multi-platform form generation. See the Developer's Guide for more information.
Functions that implement the query and component indexing. Fulcro keeps indexes of on-screen components by ident and class. These enable Fulcro to find on-screen components for things like targeted refresh. You are allowed to use the indexes to find components for whatever purpose suits your needs (e.g. looking at component options).
Functions that implement the query and component indexing. Fulcro keeps indexes of on-screen components by ident and class. These enable Fulcro to find on-screen components for things like targeted refresh. You are allowed to use the indexes to find components for whatever purpose suits your needs (e.g. looking at component options).
Fulcro is quite customizable, and all of the pluggable algorithms are stored on the app. This
very easily leads to a desire to alias the long com.fulcrologic.fulcro.application namespace
to something like app
for easy access to keyword aliasing, but in Clojure this leads
to circular references. This namespace exists simply to save typing and hassle with
respect to that. It includes app-algorithm
which can look up a plug-in algorithm on
an app using a simple keyword without having to require the application ns.
Fulcro is quite customizable, and all of the pluggable algorithms are stored on the app. This very easily leads to a desire to alias the long com.fulcrologic.fulcro.application namespace to something like `app` for easy access to keyword aliasing, but in Clojure this leads to circular references. This namespace exists simply to save typing and hassle with respect to that. It includes `app-algorithm` which can look up a plug-in algorithm on an app using a simple keyword without having to require the application ns.
Various algorithms that are used for merging trees of data into a normalized Fulcro database.
Various algorithms that are used for merging trees of data into a normalized Fulcro database.
Functions for dealing with normalizing Fulcro databases. In particular tree->db
.
Functions for dealing with normalizing Fulcro databases. In particular `tree->db`.
Functions that can be used against a normalized Fulcro state database. This namespace also includes some handy aliases to useful functions that work on normalized state from other namespaces.
Functions that can be used against a normalized Fulcro state database. This namespace also includes some handy aliases to useful functions that work on normalized state from other namespaces.
Algorithms for delaying some action by a particular amount of time.
Algorithms for delaying some action by a particular amount of time.
Functions for making and consuming Fulcro temporary IDs. Tempids are used when the client is optimistically creating a new entity and you want to be able to detect that on the server when the data is sent. Additionally, Fulcro mutations can return a remapping instruction from the server to rewrite all tempids in the client (state, network queues, etc.) atomically.
This allows the client to safely generate new entities with a temporary ID and let the server remap them to the real
IDs at some future time. Transit read/write is included, so that (de)serialization of them can be consistent whenever
needed (see the transit
ns in this package).
Functions for making and consuming Fulcro temporary IDs. Tempids are used when the client is optimistically creating a new entity and you want to be able to detect that on the server when the data is sent. Additionally, Fulcro mutations can return a remapping instruction from the server to rewrite all tempids in the client (state, network queues, etc.) atomically. This allows the client to safely generate new entities with a temporary ID and let the server remap them to the real IDs at some future time. Transit read/write is included, so that (de)serialization of them can be consistent whenever needed (see the `transit` ns in this package).
Logging helpers to make js console logging more readable. The recommended use of these functions is as follows:
(ns app.development-preload
(:require
[taoensso.timbre :as log]
[com.fulcrologic.fulcro.algorithms.timbre-support :refer [console-appender prefix-output-fn]))
(log/set-level! :debug)
(log/merge-config! {:output-fn prefix-output-fn
:appenders {:console (console-appender)}})
and you'll get much more readable error messages in the js console.
NOTE: when logging errors, be sure to log the exception first. This is documented in timbre, but easy to miss:
(try
...
(catch :default ex
(log/error ex ...))
See the development_preload.cljs and shadow-cljs.edn files in the latest Fulcro 3 template for an example.
Logging helpers to make js console logging more readable. The recommended use of these functions is as follows: - Make sure you're using Binaryage devtools (on classpath. shadow-cljs will auto-add it when detected). - IMPORTANT: Enable custom formatters in console settings for Chrome. This will print cljs data as cljs (instead of raw js). - Make a development preload cljs file, and tell shadow-cljs to preload it. - In the preload file, add something like this: ``` (ns app.development-preload (:require [taoensso.timbre :as log] [com.fulcrologic.fulcro.algorithms.timbre-support :refer [console-appender prefix-output-fn])) (log/set-level! :debug) (log/merge-config! {:output-fn prefix-output-fn :appenders {:console (console-appender)}}) ``` and you'll get much more readable error messages in the js console. NOTE: when logging errors, be sure to log the exception first. This is documented in timbre, but easy to miss: ``` (try ... (catch :default ex (log/error ex ...)) ``` See the development_preload.cljs and shadow-cljs.edn files in the latest Fulcro 3 template for an example.
Transit functions for the on-the-wire EDN communication to common remotes. Includes support for Fulcro tempids, and can be extended to support additional application-specific data types.
Transit functions for the on-the-wire EDN communication to common remotes. Includes support for Fulcro tempids, and can be extended to support additional application-specific data types.
The transaction processing in Fulcro is (intended to be) pluggable. This namespace is the implementation for the default transaction processing . At the present time there is no documentation on how such an override would be written, nor is it necessarily recommended since many of the desirable and built-in behaviors of Fulcro are codified here.
The transaction processing in Fulcro is (intended to be) pluggable. This namespace is the implementation for the default transaction processing . At the present time there is no documentation on how such an override would be written, nor is it necessarily recommended since many of the desirable and built-in behaviors of Fulcro are codified here.
Helper functions for debugging tx processing. Uses pprint, which adds a lot to build size, so it is in a separate ns to keep it out of prod builds.
Helper functions for debugging tx processing. Uses pprint, which adds a lot to build size, so it is in a separate ns to keep it out of prod builds.
A pluggable transaction processing system that attempts to batch reads. Requires that the server be modified to support sequences of transactions.
A pluggable transaction processing system that attempts to batch reads. Requires that the server be modified to support sequences of transactions.
A transaction processing system that does as much synchronously as possible, and removes various elements of complexity that were inherited from Fulcro 2 in the standard tx processing.
See with-synchronous-transactions
for how to install it.
This tx processing system does as much work synchronously as possible, though it does try to preserve the call-order semantics of the standard transaction processing: That is to say that if the optimistic action of a transaction submits a new transaction then that new submission will run after the current already-in-progress transaction has finished processing:
(defmutation g [_]
(action [{:keys [state]}] (swap! state ...))
(ok-action [{:keys [app]}] (transact! app [(h)]))
(remote [_] true))
(defmutation f [_]
(action [{:keys [state app]}]
(swap! state ...)
(transact! app [(g)])))
...
(dom/a {:onClick (fn []
(transact! this [(f {:x 1})])
(transact! this [(f {:x 2})])
(transact! this [(f {:x 3})])))
A user clicking the above link with std processing could see any of the following:
f,f,f,g,g,g,h,h,h
f,f,f,g,h,g,g,h,h
f,f,f,g,g,h,g,h,h
etc.
In sync tx processing, you would more likely see:
f,g,f,g,f,g,h,h,h
because there is no guarantee in Fulcro's semantics about the space between two calls to transact!
. If your
application relies on the groupings that happen with the standard tx processing (submissions while holding a thread
go into the queue first) then your application may break when you switch to sync processing.
Note that transactions are treated as atomically as possible. So, if you want a specific grouping you should submit it as a single tx:
(transact! [(f) (g)])
(transact! [(f) (g)])
is guaranteed to do f,g,f,g
, and never f,f,g,g
, though it is still possible to see f,g,h,f,g,h
.
This sync transaction processing system allows you to push most (if not all) behavior of even nested transactions into a single synchronous operation. This will lead to significant improvements in the snappiness of the UI for optimistic operation and should also reduce over-rendering (multiple calls to render due to multiple async operations).
If your remote is mocked as a synchronous operation, then you can also leverage this tx processor to enable completely synchronous testing of your headless Fulcro application.
WARNING: This tx processing system does not support:
ptransact!
: Pessimistic transactions are a legacy feature of Fulcro 2 that is no longer necessary. New
applications should not use the feature, and this sync tx processing system does not support it. The call
will succeed, but will behave as a normal transact!
.A transaction processing system that does as much synchronously as possible, and removes various elements of complexity that were inherited from Fulcro 2 in the standard tx processing. See `with-synchronous-transactions` for how to install it. This tx processing system does as much work synchronously as possible, though it does try to preserve the call-order *semantics* of the standard transaction processing: That is to say that if the optimistic action of a transaction submits a new transaction then that new submission will run *after* the current already-in-progress transaction has finished processing: ``` (defmutation g [_] (action [{:keys [state]}] (swap! state ...)) (ok-action [{:keys [app]}] (transact! app [(h)])) (remote [_] true)) (defmutation f [_] (action [{:keys [state app]}] (swap! state ...) (transact! app [(g)]))) ... (dom/a {:onClick (fn [] (transact! this [(f {:x 1})]) (transact! this [(f {:x 2})]) (transact! this [(f {:x 3})]))) ``` A user clicking the above link with std processing could see any of the following: ``` f,f,f,g,g,g,h,h,h f,f,f,g,h,g,g,h,h f,f,f,g,g,h,g,h,h etc. ``` In sync tx processing, you would more likely see: ``` f,g,f,g,f,g,h,h,h ``` because there is *no guarantee* in Fulcro's semantics about the space between two calls to `transact!`. If your application relies on the groupings that happen with the standard tx processing (submissions while holding a thread go into the queue first) then your application may break when you switch to sync processing. Note that transactions *are* treated as atomically as possible. So, if you want a specific grouping you should submit it as a single tx: ``` (transact! [(f) (g)]) (transact! [(f) (g)]) ``` is guaranteed to do `f,g,f,g`, and never `f,f,g,g`, though it is still possible to see `f,g,h,f,g,h`. This sync transaction processing system allows you to push most (if not all) behavior of even nested transactions into a single synchronous operation. This will lead to significant improvements in the snappiness of the UI for optimistic operation and should also reduce over-rendering (multiple calls to render due to multiple async operations). If your remote is mocked as a synchronous operation, then you can also leverage this tx processor to enable completely synchronous testing of your headless Fulcro application. WARNING: This tx processing system does *not* support: * `ptransact!`: Pessimistic transactions are a legacy feature of Fulcro 2 that is no longer necessary. New applications should not use the feature, and this sync tx processing system does not support it. The call will succeed, but will behave as a normal `transact!`.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close