One thing that occured to me when preparing a Meetup talk some time back was to differentiate between different kinds of keywords. The keys that are often named by-id
are ident keywords and are different to query keywords. I don't think it helped my Meetup talk audience at all đ, but helped me.
Hi folks, I am currently reading the interactive tutorial for untangled. I just finished reading "untangled_tutorial.A_Introduction" and when I click on the link "Let's start with the UI" at the bottom it does take me to the correct page, but I am not starting on top of the page, but somewhere in the middle. The same is true for the links "UI exercises" or "next chapter" at the bottom of page "untangled_tutorial.B_UI". Should I create an issue on GitHub for this? Or is this already known?
@fatihict Thanks for reporting, it is already known. It looks like something funny that happens with devcards but we havenât spent time trying to figure it out because itâs close enough đ. We might take a look this week, weâre doing a team sprint on improving the documentation.
Any questions about untangled so far?
@ethangracer Cool đ. I am going to read the tutorial first before asking silly questions to you guys. Also, I am a graduate intern sitting next to @mitchelkuijpers and it's really helpful that someone next to you is explaining this stuff đ. If you guys need a beginner to Clojure/ClojureScript to read documentation to verify if it is understandable, I am willing to do it đ
Oh awesome! Mitchel mentioned yesterday that you might be helping us out. We would absolutely appreciate your feedback on any and all of the tutorial documentation / videos / etc. We want to make the Untangled introduction as clear as possible
Nice, so far I've watched quite a few of David Nolen's and Rich Hickey's talks and one of Tony Kay (I really liked that one by the way). If you guys have any material I will gladly have a look and give my feedback on them đ
@ethangracer Iâll talk to the rest of the team, weâd love to write a testimonial. One thing I would be interested in hearing more about in the docs is how the Untangled team manages different views after a data load. For example, weâve found a common case to be that one component might want all the items in a table while another just wantâs a subset. It took us a bit to realize the benefits of making ident
âs for the lists themselves, like :person-list/by-id
, where the ident is :all
for the list of all items, and maintaining that list in any data loads as post-mutations.
thanks @gardnervickers! thatâs an interesting thought for a cookbook recipe, managing lists of items. Your approach is one that we havenât taken â we do something similar where we query for [{:items [:id :name]}]
, where the sub-query is on a component that normalizes to :item/by-id
. So once the data has loaded it looks like this:
{:items [[:item/by-id 1] [:item/by-id 2] [:item/by-id 3]]
:item/by-id {1 {:id 1 :name âfooâ }
2 {:id 2 :name âbarâ}
3 {:id 3 :name âbaz"}}
So that way we have the items by id automatically put into the :items
list at the top level of the app state, which we can query for from any component with [:items _]
. No need for the post mutation.Your approach leaves a âcleanerâ top level of the app state though
Ah ok we were thinking of doing that too, when you need a subset of the full list of items, do you filter after the component getâs the result of querying :items
or build sub-list through a mutation?
@fatihict awesome, Iâll send some stuff your way toward the end of the week
đ
@gardnervickers yeah we just use filter, itâs quick
Hmm that seems a lot less involved than our approach
is a post-mutation changing the react-key?
sorting into different lists would obviously be more time efficient for large data sets, we havenât had to deal with that though
@w1ng not unless you explicitly ask it to
and it wouldnât really be the best place to do so⌠you can add :untangled/force-root-render
or something similar as a read to any query and it will force a root render
Iâd have to look at the data fetch / mutation doc strings to remember exactly when it applies
@gardnervickers to your point though, itâs a fairly common requirement and we should absolutely have a cookbook recipe for that if we don't
@ethangracer thank you!
or make it easier to find at the very least
@w1ng yup!
Nice tip about :untangled/force-root-rerender - I think we've probably needed that and worked around it before. If I remember correctly, we read the "ui/current_route" param we have to trigger a rerender from root, since in our case the rest of the app is based on that.
yeah we were doing the same thing for awhile and decided it wasnât the most declarative way to trigger a root rerender. it does work though
remember that you can trigger a root re-render by just doing a follow-on read of anything the Root queries
the react-key is about forcing React to re-evaluate the render even in the face of unchanged data
typically, you only need the latter during development, and it is rather heavy-handed otherwise
We do force root render in a couple of cases (which updates the react key, if memory serves), but those might change over time as things stabilize. I think we currently do some internal forcing around post-mutations to ensure that markers are updated, but iff post-mutations are used.
@gardnervickers https://github.com/untangled-web/untangled-cookbook/tree/master/recipes/lists
thereâs a readme in there about managing lists, along with a more fleshed out example of what we were talking about earlier
Nice
What was unclear to me was specifically how to manage projections/views from different tables. The common case for us is that we have several components that all have a view over every element in a table, but some of our tables are way too big and we need to only show a subset. Analogous to youâre approach with querying lists of idents at the top of the db using links, we started making tables for our different list views like :person-list/by-id :all
, :person-list/by-id :new-york
:person-list/by-id :chicago
etc⌠That way we can default to :person-list/by-id :all
, and opt-in to building/maintaining sub-indices if things get too slow.
ahhh interesting
to my knowledge there isn't an accepted design pattern for that kind of problem yet, but it looks like what youâre proposing is a good one to me
A component (subtree) will re-render when:
- It is the initiator of a transaction
- A transaction mentions one of the things it queried in a follow-on read
- Has the same ident as a component initiating a transaction
I actually had no idea about the third bullet point, but that plays in our favor with this approach too!good point!
@ethangracer @gardnervickers That kind of is the intended design pattern. In stock Om Next you write different parser routines the try to generate (and somehow memoize for speed) various views of the same data. In Untangled, we just use app state and pre-memoize them.
then query the versions explicitly
Idents normalize everything to prevent duplications
done
make the caching story a bit more directly apparent as well
Yup thatâs becoming clear, it workâs well with things like the data-fetch/load-data
where you can just pass :ident [:person-list/by-id :all
yeah, that too
Om has the elegant design, we just chose an implementation that seemed general purpose and logical
and easier to write/maintain than a parser
Yup, I struggled with writing my own read client parser quite a bit
Are there plans to support http caching?
yes
for that to be usable, you basically need access to multiple remotes...which we also need to add hooks for
once you have that hook, everything else is up to your server code response and the browser
Ok great so itâll be like vanilla Om.Nextâs approach?
exactly
we're trying to be really thin
actually, I'd say we don't do anything differently than vanilla. We're just supplying reasonable implementations for the stuff that Om Next "leaves up to you".
parser, network plumbing, merging data, database format, i18n, support viewer of history, etc.
Om Next really does require you write a lot of code just to get started.
^^ thatâs a great blurb for the main page of the site
We're realizing that this message needs to be more central in our description of Untangled
yeah
tony are you pancia? I forget
or is he on your team
oh it's adambros
right
@jasonjckn Anthony is a separate person đ
Is he on your team or independent?
just curious
on our team
kk
i'm just eyeing his PR đ
its me!
yeah, we're making a lot of PRs for doc improvements
its actually not finished, hes talking about the defui one
the devtools one
there are like 5 of us working on that...oh yeah, that...more ideas coming there
we had lunch yesterday to discuss ideas
yah it looks like it's going to be an epic addition
we found a way, I hope, to make a complete extension point mechanism for defui...going to be really cool if it works đ
remember to test Deref / factory function in advanced compilation
I had difficulty with it
but that was 2 months ago
haven't tested advanced mode since
leave a note on the PR or ill forget
kk
data normalization works for ident joins right, anyone test this? {[:ident-kind :ident-id] [:my :query :keys]}
I want to start making heavy usage of this
@tony.kay Great description, when I was first checking out Untangled I was under the assumption it forced you into using datomic and heavily influenced youâre design decisions. As weâve been using it and going through the code base itâs clear itâs just a layer over the top.
@gardnervickers yep, I for example only use the untangle-client, my server implementation is totally apart, in node-js using sql đ
Ah interesting
@jasonjckn yes, norm and merge work with ident joins
I did just find a bug 15 mins ago related to it, though...if "not found" on the server, the plumbing crashes on ident join merges (issue #39)
@gardnervickers Yeah, @ethangracer is working on the website as we speak and trying to clear up that misconception. I'll probably add something to the Om Tutorial of that sort about Untangled đ
Neat, thankâs for all youâre hard work, this has been a pleasure to work with.