Fork me on GitHub

"Thanks @dnolen" is that some kinda meme on this channel? I see it a lot..


Too bad gratitude isn't a meme on the Internet at large.


In my app, a component represents an autocomplete search (customer-search). For this search it queries for all customers by name. In this case, i made a :shared value that is a filtered database:

(def reconciler
    {:state  conn
     :shared {:customer-db (d/filter @conn
                                     (fn [_ datom]
                                       (= (.-a datom) :customer/name)))}
     :parser (om/parser {:read read :mutate mutate})}))  
. As far as i understand, i need to rerender the root, if i want to update the :shared values. correct?


@thomasdeutsch: to update shared, yes


@thomasdeutsch: My understanding is that you must used :shared-fn to apply updates, which will merge into :shared. I


I'm working on :shared-fn today, so I'll pipe up if I find anything otherwise, or any gotchas.


@dnolen: experimenting with :shared-fn, and I'm finding it does not get called when the root component is re-rendered, only when (om/add-root! ...) is executed. Is that intended behavior?


@bplatz: not intended


@bplatz: this is probably an edge case where the root component gets updated directly instead of just calling the root render fn


file an issue


@leontalbot yes, it works


@andlai There you go!


@bplatz: thanks


if i’m working with datomic, it’s unclear to me how i’d resolve tempids when my transaction is wrapped in a thunk:

(defmethod mutate 'item/create
  [{:keys [conn]} _ {:keys item/om-tempid}]
  (let [db-tempid (d/tempid :db.part/user)]
    {:action (fn [] @(d/transact conn [{:db/id db-tempid :foo "bar"}]))
     :value {:tempids {[:item/by-id om-tempid]
                       [:item/by-id resolved-db-id]}}})) ;; how to resolve db-tempid?


anyone else run into this yet?


@joshfrench: So, that is Datomic server side mutate, right? (not Datascript)


@tony.kay correct


I don't think you have to put the transact in action. The parser calls the action on return, but that has to do (I think) with the UI concern on the client


really the value is all you care about on the server


that was my best guess: run the transaction above and just deref it in the return. but i wasn’t sure if that was allowed server-side.


I cannot think of any reason why that would be the case


(but that is also why I say "I think")


it is meant for side-effects on app state is my understanding, and there is no "app state" on the server


nice shrugh (props for the creative use of katakana)


you can prepend /shrug to anything in slack!


so are there any working examples of tempid migration out there? i was looking at but i can’t get it running and i’m hitting the limits of what i can glean just by reading code


Any thoughts on differentiating between refs and vectors in read implementations in order to support writing a recursive parser that automatically follows refs? I was hoping I could annotate my idents with meta data and the refs in the state (put there by tree->db) would preserve the metadata from ident but that seems not the be the case.


This works for my current data but is really dirty and falls down for data that looks like a ref

(defn ref?
  (and (vector? val)
       (= 2 (count val))
       (keyword? (first val))
       (not-any? map? val)))


I am coming from js react and new to I have a textarea in an component with an :onChange handler which updates local state using om/update-state! This triggers a render of the component so that the value of the textarea changes in the browser as I type. All good and as per js react. However the properties of the component, which were there for the initial render, seem to be lost on the subsequent renders caused by the update-state. Is this expected? Do I have to copy all the props to state? Or does it just sound like I need to look harder at my code? Thanks.


@colinf: I don’t think your props should ever get lost, and you should never have to copy props to state. Its hard to know whats wrong without knowing more about your code. Are you using Om as shown on the readme or trying out


@noonian: I’m trying


colinf: I suspect it is something with your read impl. I’ve had similar problems but can’t remember what caused it. I would make sure that you can call your parser manually with your root query after your app gets mounted and ensure that it gets the right data. If your read fn isn’t finding the correct data in the app state on reads after the first on I think you would have this problem (so update-state! might not be relevant except that it is exposing the problem by causing the re-render).


@griffio: Cool - thanks for that. You have used om/transact! to update app-state for each text keystroke. My failing code uses om/update! for each keystroke and then om/transact! to update app-state only on keydown of enter (i.e. data entry finished). I can try your way to see if that eliminates the problem.


om/update-state! should still work though


and it appears that it is if the text area gets the state correctly


which is why I think it is something to do with how you read the data from your state


@noonian: It took me quite a while to get my mind round the reads with composed queries and recursive parsing, so I won’t be surprised if the problem is in there! This component has no query - it is passed the initial props from it’s parent which seems to work fine for the initial render but then not after an update-state. Maybe I can also try rolling the data entry component up into its parent.


Hmm, I’m not sure then. It could also be a bug in Om. The re-rendering code may not have been exercised that much for components without queries that have component local state.


@noonian: I added a query to the component and it works fine now. In my tiny mind I didn’t need to query as I had already “read” the data in the root query i.e. there was no new data involved. But I obviously need to think differently! Cheers


@colinf: Nice, I’m glad you have it working


Om does support query-less (reusable) components though. It would be nice to know why your component wasn’t receiving its data.


@noonian: I may stumble across an explanation while finishing my experiment with, but if not I will try to isolate the issue


Yeah, I’m just curious 😛


@joshfrench: Sorry, that copaste experiment is very much WIP. If you pull the latest master, you should be able to get it running with GIT_DIR=/tmp/copaste-store.git git init && boot run-development


@jannis how do i make clj-consonant available? boot install throws "java.lang.Exception: can't find jar file” even after i run boot jar. (sorry, totally new to boot.)


@joshfrench: Ah, of course, it's not on clojars. You can clone it from and install it locally using boot deploy when inside the repo.


boot deploy is what i was missing, thanks again!


Once copaste is running, open and you should be good to go. simple_smile


super helpful to see some of this in action, this is great. much obliged.


@jannis: whats the consonant thing this is a clj version of?


@joshfrench: Not sure how much you can learn about tempids by looking at it though. I'm simply taking the UUID portion of the tempid, use that as the real ID, store it with that ID on the server and then return the pair. How you do it depends on the data store. Some may allow you to create the ID post-creation, others return the created entity with the real ID...


@martinklepsch: - it's something I drafted quite a while ago 😉


@jannis right now i’m seeing what sounds like a bug you ran into, where migrating actually destroys my local tables. but i’m up to date on transit, so i don’t think it’s the same root cause. i’m hoping to spot some obvious difference in the actual behavior here, now that i can see what you’re sending/receiving.


@martinklepsch: I'm toying with the idea again to see if I can simplify the concept somewhat and make it more Clojure-friendly. Not sure how much of a point there is since there's Datomic but it's bugging me that I never got to finish implementing it.


@joshfrench: I'm using a custom merge tree function. The default one doesn't perform a deep-merge of maps.


i saw that, i wasn’t sure why though. sounds promising, i’ll have to dig in.


@joshfrench: So if you have something like {:people {5 {:id 5 :name "John"}}}, returning {:people {6 {:id 6 :name "John"}}} from the server will simply replace the value of :people.


While what you may want (depends on your tree structure) is to a few levels deeper to maintain local properties and temporary local people.


may have to do with the fact that i’m not returning anything except tempids


which might be a mistake?


Could be. I'm trying to remember whether the server-side :keys returned via :value are used or not. On the client-side they are ignored.


Are you performing any post-mutation reads?


And is your code public? 😉


i’m not, and it is not 😛


but lots to try here, and i can reduce it to something showable if none of them work.


Returning no :keys from the server-side mutation makes no difference.


If all you do is call (om/transact! foo '[(app/create-your-thing)]) with no reads and you're returning :tempids, it shouldn't throw everything away. It should only migrate to the real ID.


@joshfrench: It expects your data to be structured like {:items [[item-by-id 1] ...] :item-by-id {1 {:id 1 ...} 2 {:id 2 ...}}}. Perhaps that's your poblem. Also, are you aware of :id-key (reconciler option)?


normalization doesn’t seem to be the problem, everything is properly normalized up until i migrate. and i tried :id-key with no luck.


actually post-migration everything is still normalized, just nilled out all the way down the tree.


Hmm. I can only guess. Reads sending empty queries to the server?


another good theory. i’ll have to spend some time reducing this.


Do that. simple_smile I'm happy to help more tomorrow.