Fork me on GitHub

I'm trying to run my Fulcro app with an actual Datomic instance. I installed Datomic, and the transactor is running. Datomic says "System started datomic:sql://<DB-NAME>?jdbc:<postgresql://>, you may need to change the user and password parameters to work with your jdbc driver" (it seems to run fine though, no errors). So subsequently I started my Fulcro RAD app, but I get this:

Jakub Holý (HolyJak)16:07:35

Ask in #datomic? Try to talk to the DB manually from the REPL? Check your config?


I re-did everything and then it worked 🙂


Hi when I user load!with :target (append-to [:persons]) I get duplicates in :persons. Does anybody have any hints what I am missing?


Without having tried it (or knowing if it is possible), try telling the component that the datatype of :persons is a set, by setting its value in initial-values to an empty set


Ah. So my description was to short. I have many persons with [:person/id :person/id] and uuid as :person/id already on screen and they render fine. There in a vector of Idents in [:persons]which points to them. So all normalized and working fine. When I search for more people and the database sends some and I do a load with :target [:persons]it works fine, but clobbers the previous vector of idents there, so now only the people returned from the server in the search are listed, the people who were already in the DB are gone from :persons. If I now replace :target [:persons] with :target (append-to [:persons I do not get duplicates in :person/id table but I do get duplicates in the vector of idents in :persons that points to them.

Jakub Holý (HolyJak)16:07:11

I think that is expected behavior. Read the book on data merging. Upon load it I guess simply replaces the value. And append to obviously appends to the existing vector. Look at what other merge algorithms there are or write your own. Or, if possible, try to use a set instead. It is kind of weird thing to need what you require. Either you load all data at once or, eg with pagination, you load page by page (where append to is perfect)


Without looking at the code my memory is in agreement with @U0522TWDA that merging of new idents into an existing list is not included in the provided merge algorithms. I have done this and I would use it if it was added.


Thanks! That makes total sense, I did not consider the pagination. In algorithms-data-targeting the doc-string of append-to includes in the doc-string NOTE: this kind of target will not create duplicates in the target list. So is the duplication intended?


@U0CKQ19AQ would you be interested in a pull request to change data_targeting/process-target to remove the set of existing idents from item-to-place before appending/prepending into state?


or would that be a breaking change?


@U15BH4U4V breaking change. That behavior is intentional. Duplicates are often errors (reloading something will update its values, but you would not want it doubling the list) I would accept a PR for new data target names like clear+append


Also, have you considered different attribute names for your different purposes? Why not have an attribute for search results, and combine two lists in the UI?


I have to think about that to make sure I am not solving the wrong problem.


Hi @U0CKQ19AQ, here is the scenario I use this for. Maybe there is a better way to go about this. For many entity types I keep a list of idents in root as a pick-list. For example, :persons as a list of idents to :person/id so I can add a person-dropdown anywhere in the app. So every time a new person gets *load!*ed I need to add/append to [:persons] without duplication for later availability in picklists. The :persons list does not only get used for dropdowns but also for overview-pages like person-list-page. Other method tried: Calculating the drop-down realtime from [:person/id '_] did work except when the component I needed the person-dropdown on was itself a :person/id. In which case the query {:query [:person/id [:person/:id '_]]} would clobber itself. So I switched to the above method to have dropdowns work consistently. Alternative to the append-to at load time: Instead of appending to the pick-list at entity-load-time I do have ensure-picklist-updated-mutations that can be run from componentDidMount on the components that need the list. But I also load new persons while the lists are already displayed so the append after load is really useful. Advantage of the :persons in root: This list can be sorted so it represents a last-used order. Users really want that. So in the UI it can be orderd as is, which is last-used, or it can be sorted to be alphabetical etc. Do you have any insights or suggestions how to go about this in a better way?


Stop complecting uses of persons? 1. Doing it from table with [:person/id '_] : Problem: If you load partial list of persons, dropdown breaks. Dropdown’s internals have no coherent lifecycle for the data they need. 2. Keeping a root list of idents: Fine, but only as long as what’s in that list is directly controlled by the dropdown logic. Same as (1). If your dropdown isn’t in control of the loading story, then you’re relying on disconnected logic in the app to ensure consistency. In RAD I create a picker cache, which is a normalized area for entity picker options. You can choose to normalize (or not), and you can choose a cache key different than the query key, and you can also set a stale timeout. Dropdowns call an “ensure options” mutation on mount, which checks to see if the cache is stale and loads them if so. Dropdowns are completely in control of what they show, and can now even have custom resolvers that resolve special lists of options from the server without any client computation. More than one picker of the same kind can be on-screen and will share the same cached data as long as they use the same cache key.


Thank you!


It works if I write my own append-to and call it in :post-action


Yes, so did you try :initial-state {:persons #{}} ?


initial state is a vector or map….not a set, FYI