This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-09-04
Channels
- # beginners (14)
- # boot (28)
- # chestnut (9)
- # cljsrn (18)
- # clojure (64)
- # clojure-conj (1)
- # clojure-dusseldorf (45)
- # clojure-finland (4)
- # clojure-gamedev (1)
- # clojure-greece (8)
- # clojure-italy (22)
- # clojure-russia (4)
- # clojure-spec (19)
- # clojure-uk (38)
- # clojurescript (49)
- # code-reviews (2)
- # component (12)
- # core-async (3)
- # cursive (3)
- # data-science (2)
- # events (4)
- # fulcro (394)
- # heroku (3)
- # hoplon (16)
- # immutant (11)
- # jobs (5)
- # lein-figwheel (1)
- # lumo (18)
- # off-topic (8)
- # om (11)
- # other-languages (1)
- # overtone (1)
- # pedestal (7)
- # portkey (62)
- # protorepl (1)
- # re-frame (40)
- # reagent (41)
- # ring-swagger (5)
- # spacemacs (5)
- # unrepl (5)
- # yada (12)
I should add sanity checking for the form fields. Unfortunately that is a little thougher since you can define arbitrary form field types via your own functions, so there is no easy way to detect what the field name is reliably
I guess I could just make it a restriction: if you want to use custom field types with defsc, then the field spec constructor functions must take the field name as the first argument.
@tony.kay honestly, I think this macro is too magical... I like using the raw om defui
. and I would be careful about having the properties at the definition, I remember the old om got away from having as parameters for a reason (forcing people to call om/props
, if I remember right was a problem on callbacks or something). one question: how is the ident being infered, I see the table for the namespace part, are you assuming the db field would be always :db/id
?
about the forms, I tried to use this yesterday, but I though it was too much... did you though about using specs to run the validations instead of having a separated multi-method system?
how come? you define the keys, and define a s/keys for the composition, looks very matchy to me
Then it is too weak. Write me a spec that checks that :password and :password-again match in a map
I mean, we have field names already, why have to create a new key->predicate map?
(s/and (s/keys :req [:user/password :user/password-confirmation])
(fn [{:user/keys [password password-confirmation]}]
(= password password-confirmation))
@tony.kay that's how ^^^
Right, assuming they are inthe same map…that’s right. I was thinking about them as separate fields.
when we are editing a form, we are basically editing a map, so we just need to validate that map
it's much easier and simple if you keep then in 1 map dont you think?
so, I’m game for a contribution that allows the use of spec for validation. But,you have to solve a couple ofproblems: 1. Matching the validation problem up with a form field 2. Nesting forms and validation
spec is great for nested, the (s/explain-data)
can give you the exact paths for the problems
So, other than your obvious extreme preferece for spec validations, what else did you think? 😛
I kind feel weird to declare parts of the input (view-wise) properties on that extra protocol... it might be a preference think, but I like better when I'm just provided a set of small tools that I can work with, and with forms it seems that extra layer requires too much and I don't see that much gain (trying to say: with smaller helper functions the same can be done without so much contract). I would like to see more just tools that can improve on the already existing structures, but helpers like defsc
seems to drive users away from the more full featured approach, I just not sure if the sugar gain pays of
So, when provided with those small set of tool, you end up writing generalizations. The added form support and defsc are just an added layer of abstraction on top of the base tools. No one says you have to use them.
In the forms case, it generalizes and standardizes a pattern that a lot of people are goign to write over and over. It gives devs a framework to repeat instead of invent. With defsc, the added sanity checking prevents common errors, and becomes easier to read because of the reduction in boilerplate.
I would just recommend going easy, maybe leaving the sugars to teach later on the docs and things, it's kind easy for us that know it already, but for who is comming those extra layers can add more confusion on how things work IMO
And forms are actually kind of hard to get right. You have the “unedited” dirty state to track separately from the edited state, submission deltas, etc etc.
but hey, I want ot congrat on how complete the devguide is getting, it grew so much in the last weeks, you are rocking on it 🙂
one thing about forms, you could try to leverage the keywords more
that’s why I added the reference guide. I was thinking a lot of the details should go in something like a ref guide instead
even if not just for specs, but the keywords have value by thenselves as unique idenfiers
you could use then to choosing form fields for example, instead of doing at the component level
it's always good to be able to override, but most of times they work the same
I think validations are better here, because the form is really about the layout, validation is more easy to share
So, I agree with you that spec is probably the better way to go with form validations. I’m a little concerned about the namespaced keyword collision possibilities and how to handle them.
and from a practical perspective, the whole-form validation would have to be declared somewhere…hooking it all up isn’t clear to me at the moment
Rembmer that we have some global function that generally understands form support. When triggered, it has to figure out what validations are needed, run them, and mark the form field data on that particular bit of state.
I guess we could add a special entry to specify the spec for the form in the IForm form-spec
.
static IForm
(form-spec [(f/id-field :db/id) (f/validation-spec ::my-form) ...])
it can be easier than that
let me show you one code example
(s/def :person/name string?)
(s/def :address/street string?)
(s/def :address/new (s/keys :req [:address/street]))
(s/def :address/list (s/coll-of :address/new))
(s/explain-data (s/keys :req [:person/name :address/list])
{:person/name 123
:address/list [{:address/street "ok"}
{:address/street true}]})
that outputs:
#:clojure.spec.alpha{:problems ({:path [:person/name],
:pred clojure.core/string?,
:val 123,
:via [:person/name],
:in [:person/name]}
{:path [:address/list :address/street],
:pred clojure.core/string?,
:val true,
:via [:address/list :address/new :address/street],
:in [:address/list 1 :address/street]}),
:spec #object[clojure.spec.alpha$map_spec_impl$reify__483
0x691dd42
"clojure.spec.alpha$map_spec_impl$reify__483@691dd42"],
:value {:person/name 123, :address/list [#:address{:street "ok"} #:address{:street true}]}}
if you look at the :problems, you can see all the info you need to infer the field
so you might just need to have 1 spec for the full form
and by running the explain-data you can get the information to fill in
maybe 🙂
ah, sorry, I think I got now
that f/validation-spec is the indicator for the form
sorry, read wrong before XD
well, perhaps not…I think that does get us validation. Once the markers are in place (which you’d have to translate to the graph db paths) the existing stuff should work, since rendering is separate from validating.
Oh, actually, validations that are not directly associated with a single field are a problem
what misses there is how to relate that error with the fields, right?
The rendering is based upon a marker on a field. “If this field is invalid, show this message”
yeah, that's tricky
because you can only return a false
to handle the error, not sure how to provide that information part
I mean, the existing on-form-change could be leveraged still to deal with that. The mechanism will always be needed anyway
e.g. “Do you like animals?“. Answer yes and the form changes to include a “Pick your favorite”
@wilkerlucio what do you mean return false?
I mean you can't provide extra error information, the spec validations are just simple predicates
maybe we don’t have a full-form (clojure) spec at all…just some way of indicating that specs should be used against namespaced props if available.
That gets you a kind of automatic form field validation system with the spec registry
hm…that would be a lot of breaking API changes. Declaring it on the form itself during form init is better.
it's complicated...
hehehe, we will see, but for now I prefer to stay simple, just a couple helper functions here and there, maybe I didn't got complicated forms as you may have
The features I felt were necessary: keeping the old state vs the edited one. Being able to revert a form. Being able to submit a delta. Being able to nest forms and have them submit as a delta of the graph.
Now that spec is more commonly available, I agree that it is better for field-level validation.
Oh, and the ability to do global form change monitoring that can do global validations and form state changes based on inputs.
All of those things can be constructed by hand for a form. Obviously. The dirty state management is the most important feature, IMO
@wilkerlucio and I would like your feedback once you actually to try defsc
…particularly the sanity checking. We make mistakes all the time with defui
, and it has already caught me screwing up a couple of times just playing with it. I’m not all that worried about the boilerplate, but catching errors like “you destructured something from props that you didn’t query for” is pretty darn nice.
ok, I'll give it a try
what about calling :query
instead of :props
?
I find that odd, because in Om we call it query
I have one suggestion on the table field (this I would like be called ident
, haha, sorry asking so much)
defsc
is not meant to replace all defui
, just the common case of plain props and children
but the recommendation on table is: if user provides a vector, you can use the second item to be key to be fetched from the props
eg: {:ident [:user/by-id :user/id]}
just to keep the names and avoid extra mind translations 🙂
and since we are there, would be nice to accept a function there too
because there are more complicated cases, like this one (real case):
(ident [_ props]
(let [[owner name] (str/split (::g.repository/name-with-owner props) "/")]
[:github.repository/by-owner-and-name [owner name]]))
so, I’m trying to walk the line with you of “too much” vs “too little”. If there are too many options, it becomes more difficult to understand. Too few options and it become too weak.
yeah, I like the vector case because I think is the most common
and the function one is the most flexible
supporting both is a good cover range IMO
tradeoffs 😛
is the css stuff supported there?
this is my current snippet for fulcro components:
(om/defui ^:once $COMP$
static fulcro/InitialAppState
(initial-state [_ _] {})
static om/IQuery
(query [_] [:$ENTITY$/id])
static om/Ident
(ident [_ props] [:$ENTITY$/by-id (:$ENTITY$/id props)])
static css/CSS
(local-rules [_] [])
(include-children [_] [])
Object
(render [this]
(let [{:keys []} (om/props this)
css (css/get-classnames $COMP$)]
(dom/div nil))))
(def $COMP_LOWER$ (om/factory $COMP$))
pretty much
would be too hard to make the config extensible?
maybe another multi-method
I'm serious
maybe, that might make me more willing to use it if I can extend it, hehe
yeah, it is possible to do that, but remember that you’re working with a macro here, so load-time issues turn multimethods into a nightmare
yeah, that is this to consider
I think on this case the multi-method might live on clojuer side
but maybe is not that bad, if we can throw some data to the extension points like a pipeline, and then you get the combined thing and make into the final result
bikeshedding, maybe XD
So, I can say the last time I tried to use multimethod to modify a macro’s behavior, it did not go well
I mean, it sounds like a cool idea…because that would make defsc
fully extensible…like with mix-ins
Ah, clojure isn’t hot code reloaded…if you make a multimethod add-on to your defsc, you have to restart figwheel to try it
urgh... at least this extension should not be something people do very often (I hope)
So, an alternative is this:
(defsc Component
[this props computed children]
static css/CSS
(local-rules [_] [])
(include-children [_] [])
{ options map }
body)
bleh…that makes it extensible, is easy to code into the macro, but looks like shit-on-toast
humm, how do you figure where the protocol implemention ends on that?
you can enforce the body to be one
(do)
is always there anyway 🙂
I still don’t like how it looks…but I’m not liking any of the extensible options I can think of
I was going to ask if you ever had a non-static protocol
but then I remembered I actually did XD
oh, I though I did, but wasn't, still a static call here
They’re supported…but I’m in agreement: I wasn’t necessarily interested in the fully general case yet, just a common one that could save some headaches and boilerplate
I have not been using co-located CSS, so the way I wrote defsc
covers over 90% of my usages.
but rather than expanding the options
for expansion, I was considering just letting you do the defui
thing in the middle like that…I just don’t like how it looks. I like the idea of some kind of chain-of-responsibility add-on, but I don’t like the dev flow for it.
this doesn’t seem better, other than the structure is cleaner:
(defsc Component
[this props computed children]
{ :props [:a]
:protocols (static css/CSS
(local-rules [_] [])
(include-children [_] [])) }
body)
maybe call it just :protocols
the editor is not monospaced font I guess
so it's not WYSIWYG in that sense 😛
Given that CSS is a formal extension lib and they are just symbols, I’m tempted to make CSS a first-class citizen of the macro, add :protocols
for everything else (including lifecycle on Object).
it doesn’t create a hard dep, and you’d only use it if you use the CSS lib (and require it somewhere to load it)
I would prefer to send vector instead of a list to :protocols
, I guess you can just avoid enforcing the list type and any will work as same (probably just a ~@protocols somewhere anyway)
and you can even leverage the children
and automatically fill-in the include-children
probably better to have both as complementary (concat or something)
I think I’ll start with just support for protocols. The CSS has some twists that I’m not sure make it much advantage to augment. The children cannot automatically be reliable, since you might have CSS children that are stateless
yeah, that's why I suggest as complementary, so if it's not part of your query, you can add on a :css-children
key
although :children
could be extended to auto-detect…does it have a query? does it have CSS?
that sounds interesting too
I like that
why is that?
oh, good point
I’ll start with :protocols
, it doesn’t hurt anything, and doesn’t really complicate anything either.
@wilkerlucio got a suggested clojure spec for that 🙂 ?
nope, all good I guess 🙂
but lately I've being very inclined to use more namespaced keywords everywhere
you could use some specs to validate the input for the defsc
macro
I was just thinking my spec chops are not quite up to a spec for what we just described in :protocols
just declare it as a (s/coll-of any?)
for now
a sequence of one or more of an optional static symbol, followed by a namespaced symbol, followed by one or more method bodies…
I’m going to need to parse it…might as well do it…I aleady wrote the extension…it was trivial
(s/cat :protocol-name symbol? :protocol-methods (s/+ ::protocol-method))
it really feels like Clojure should provide specs for protocols
yes you can do s/?
on cat 😉
(s/cat :static (s/? #{'static}) :protocol-name symbol? :protocol-methods (s/+ ::protocol-method))
yup, might need some tweeks, you can use (s/spec)
to break on some situations
but I didn't used regexp specs much, but looks a good place for it
I think s/*
is more apropriated on this case than coll-of
and coll-of wouldn't work, because they are in flat list (concated)
(s/def ::static #(= 'static %))
(s/def ::protocol-methods (s/+ list?))
(s/def ::protocols (s/* (s/cat :static (s/? ::static) :protocol symbol? :method ::protocol-methods)))
(s/conform ::protocols '(static A (x []) (y []) B (f [])))
=>
[{:static static, :protocol A, :method [(x []) (y [])]}
{:protocol B, :method [(f [])]}]
I was playing here too:
(s/def ::exp (s/cat :static (s/? #{'static})
:name keyword?
:numbers (s/+ int?)))
(s/conform (s/cat :protocols (s/* ::exp)) [:a 2 3
'static :b 3])
=> {:protocols [{:name :a, :numbers [2 3]} {:static static, :name :b, :numbers [3]}]}
I would breakt your organization just a little bit different:
(s/def ::static #{'static})) ; <- shorter, and generator friendly
(s/def ::protocol-method list?) ; <- singular here
(s/def ::protocols (s/* (s/cat :static (s/? ::static) :protocol symbol? :methods (s/+ ::protocol-method))))
(s/conform ::protocols '(static A (x []) (y []) B (f [])))
makes sense?
then you can make the protcol-method more complicated if you want
this leave the many
decision to later
also, make the ::protocols
cleaner to read (you see the regex entirely there)
no problem, good walk on 😉
@wilkerlucio OK, :protocols
added and on clojars with beta10 SNAPSHOT.
pushed again. No longer uses :table
and :id
, but instead uses :ident
. At present, does not yet support a function.
So, that covers all defui
cases, with the following exceptions:
- Complex queries (beyond regular props and regular joins)
- Idents that need to run real code against props to figure out the ID
The latter is easily fixable. The former might be. I am thinking about using :query
and allowing any query. I can extract the props and children from such a query, which can still allow sanity checking. So, I guess consider defsc
to still be unstable in API. Any additional feedback is welcome.
@wilkerlucio CSS support added. props/children changed to :query.
I cannot make ident accept a function without breaking sanity checks. I need to know what the ID prop and table are called, and arbitrary code execution in a macro to try to eval that is not possible. So, I think defui
is how you get that kind of ident.
Technically, you could still use defsc
, not specify :ident
, but instead put it in :protocols
. That would disable some error checking, but would make it work.
So, I think that makes defsc
almost completely general, a bit more opaque, but also a lot safer to use:
- Cannot forget the static
on main protocols (Ident, IQuery, InitialAppState, IForm, and CSS)
- Prop destructuring is verified against query
- Initial state is verified against query
The one case that it still won’t handle is a union query.
Really loving that defsc support css, would still find it cool to make it extensible with own keyword somehow the case with protocols looks pretty ugly imho
is there a way to specify refresh keywords to a post-mutation?
@roklenarcic: You can refresh from the transact!
or the load
(which calls transact!
for you). In the latter there is :refresh
that you can set. You can't refresh (also known as 'follow on read') from within a mutation.
Hm well the load has the refresh set, but it seems to apply refresh after load, but before the post-mutation
it probably applies refresh parameter to mutation that does the load, but not to post-mutation
Just looking at the load documentation: "`refresh` - A vector of keywords that will cause component re-renders after the final load/mutations."
That does explicitly say 'post mutation' unfortunately. But I would assume that the refresh comes after the post-mutation - as post-mutation instruction is bundled up together in the load
call.
Are you sure your refresh is working? I often find when in trouble that refreshing using an ident always works.
If I run the same load twice it works
the second time refreshes the other component
"But I would assume that the refresh comes after the post-mutation - as post-mutation instruction is bundled up together in the load
call" -> I'm not sure that assumption is correct. Seems to me that post-mutation is a whole another mutation.
🙂 I was disappointed that it didn't work the way I wanted it to, as well 🙂
But if my assumption is wrong I can't see how you could refresh after a post mutation. So I'm sticking with it for now... 🙂
The transact!
is done for you so you can't do a follow on read. Only makes sense that the :refresh
is all about doing the follow on read that you can't.
If you wanted you could skip using the refresh vector in load if post-mutation is present and then use the refresh vector when transact! is called for post-mutation
But the post-mutation is not a query - it is a mutation. You need a query to put the follow-on read. The query being the thing that transact!
takes.
right, so you transact! ['(post-mutation-symbol post-mutation-params) ~refresh-vector]
Yes - 'parse expression' is a better term than query I guess: '[(do/this!) (do/that!) :read/this :read/that]
I'm doing a transact!
that contains a load-action
which has :refresh :post-mutation
Right - that's the one you need to use if you want to load
but you are already in a mutation.
That's a good point you have there - you should expect the refresh to work even though you are in a mutation. So I was wrong what I said before about not being able to specify a refresh/follow-on from within a mutation. You ought to be able to have the refresh work for you.
I do have one case of what you are doing in code that I have. It uses an ident and presumably it works. (And also presumably the :refresh [ident]
is actually needed).
I think the post-mutation refreshes the component itself
the thing is that my post-mutation modifies the side-bar, which doesn't get rerendered
unless I click the thing again, in which case the :refresh key in load action refreshes it
so the key in my refresh vector is a correct one
Well follow on reads are actually the exception. this
is passed into a transact!
so the component you did the transact!
in is automatically refreshed - there's no need for follow-on malarkey in the usual case of where the event is happening at that component and all components below refresh (automatically).
Usually you make sure you are doing transact!
high enough in the tree (ie towards the root, the top) that refreshing is just automatic.
In an extreme case you could do all your transacts!
from the root component and you would be guaranteed to have no refresh problems.
I guess I could move the first transact higher
see what happens
btw has anyone tried to use load-field-action
with :params
specified?
@roklenarcic Regarding load-field with params. Om Next has a bug that will break that. It is fixed but unreleased.
Regarding :refresh
. It is a vector of keywords that get added to the load mutation transact. The intention is for that to indicate what should be updated when the load completes, including after the post mutation. Big caveat: You must name a keyword whose actual data value has changed or it will still short-circuit the update. Now, if that still isn’t getting you a refresh, then it should be considered a bug.
Technically post mutations are not run in transact!
because they are run as part of the internal network processing. So, instead the keywords you list on refresh are added to the render queue directly.
@mitchelkuijpers Try making a macro that is extensible and use it from clojurescript/figwheel/hot reload. It is miserable. I think :protocols
is the best option, and since you shouldn’t need it much, I’m not sure it matters in the large.
I named the keyword that is the toplevel keyword for the whole screen. I'll keep looking
@roklenarcic Here is the refresh logic: https://github.com/fulcrologic/fulcro/blob/develop/src/main/fulcro/client/impl/data_fetch.cljc#L425
You should not name an arbitrary keyword. Name a keyword for specific data that actually changed.
though I would assume that a join keyword for the screen in question should be sufficient.
and force-render
is: https://github.com/fulcrologic/fulcro/blob/develop/src/main/fulcro/client/util.cljc#L32
So, if what you are doing is not working, then either there is a bug that I don’t see, or you’re sending something incorrectly to :refresh
you were right
I had a bug, where I accidentally embedded :refresh
element too deep
thank you
glad it wasn’t a bug in fulcro…those always feel like anti-progress, especially when in code that is that critical to functionality
FWIW one thing I couldn't get to work though, was load-field-action
where the field keyword was :parent
and the component had a recursive query [:id :name {:parent '...}]
. denormalize*
threw an error ... is not Sequable
when it tried to process my return {[person-by-id 1] {:parent {:id 2 :name "parent" :parent nil}}}
. It's possible I was doing something wrong again, but I didn't see any recursive query samples in the documentation, so I don't know how many people tried to run recursive queries with load-field-action
yet.
I've moved away to another solution already
so, that would be a bug in Om Next if it is broken…here are the things I see possibly wrong that could be typos:
- :person/by-id
is missing a colon…prob a typo here
- Returning :parent nil
is possibly wrong…try eliding :parent nil
altogether
- You’re missing :id and :name in the top-level map, but that shouldn’t crash it
since it was load field, the actual query to remote was {:parent '...}
only
cannot load field on recursive queries?
3 levels
If you need to lazily load each level, I’m afraid you’d have to code three different defui
, one for each level. You could use shared functions to provide impl
I got a feeling recursion doesn't mesh well with om model of denormalized database, the explosion of data can be immense
also circular idents
the recursion is fine…it works pretty well. There are some things you have to be careful about. In this case, the problem is you’ve narrowed the query to the point of being informationless 🙂
good to know
To render a loop correctly, you need to use computed props to track depth or refresh gets wiggy
I believe I saw an example with :friend
somewhere
Say you render A with spouse B, but it is the same code with a recursive query. No problem on initial render; however, if you refresh B with a transact, the context will start at B and you’ll render a new A, ending up with A B A on the UI
so when you refresh B the first time, you know you’re already 2 deep and can short-circuit the extra depth render
hm, but how does the props
get generated when denormalized without going infinite
does it use mutable JS maps and cross reference
(fn process-query [query data idents-seen] ... (process-query subquery data (conj idents-seen x)))
kind of thing
you have to watch out for unresolved idents when parsing props
then
there are probably a number of “bad data” cases that could cause problems. With an infinite number of ways of screwing up an arbitrary data structure, I’m sure you can cause bugs with malformed data 🙂
An ident that points to nowhere is almost certainly a bug in your code. normalization will always put stuff in a table when it makes an ident, even it the ID comes back nil
but yes, If you screw up an ident that you create and point it to nowhere, then you could possibly see unexpected behavior. I’m not sure that results in anything horrible…probably just empty query results.
kinda like the load markers, basically cause an empty list at that point in the tree
load markers don’t cause an empty list (though they may displace a list while loading is in progress)…returning an empty list does 😉
their intention is to let you render a loading view in place of said item or list…and you turn them off when that isn’t what you want to do
That's true @tony.kay and can always create a macro if needed
is there some way to access what was loaded in post-mutation?
what do you mean? You have the entire app state, and you issued the load. If you need more info from the call site, pass it as a post mutation parameter
That's what I do now, I pass the location where the loaded thing will be as a parameter
I load something then move it into a list in post-mutation
I move the ident in post-mutation and prepend it to an existing list
I call it in post-mutation
then yes, unless you make a mutation that is site-specific (where the incoming item location would be well known already), then you have to pass it as a parameter
alright
So, some thoughts: loads are targeted at root by default, and you :target
them…but normalization is moving your item into a table.
nvm…that doesn’t help. you’re needing to know something like “where did the transact run?“, right?
which is :ref
in a normal mutation. This came up over the weekend, too. I’ve been resistant to adding :ref
to post mutations because you’re pretty far removed from transact and the component, but it is technically feasible to pass it through…though it is a rather large and invasive change because of the length of the chain from transact, through loads (and async callbacks), back to the post mutation.
hm I defined a mutation which has a (conditional) load-action
which has the same mutation as a post-mutation. The recursion doesn't seem to work
should this work or is this forbidden?
@tony.kay We have several spots where we supply ref
through our fallback handlers and post-mutation-params
to get around not having ref
. It would be a welcome change to have as much of the transact env
intact as possible in both fallback handlers and post-mutation
‘s.
@gardnervickers I agree with you, I have the same problem in a lot of places. to be honest I would love to see a more full-featured enviroment in the post-mutation, as a dev I like to have most information possible available, I find the limited environment on post-mutations restrictive
@roklenarcic should work fine. It isn’t recursion (though you could cause yourself an infinite loop). Make sure you are using the same (namespaced) symbol.
@gardnervickers @wilkerlucio So, I’m getting that. :component
is out, but any raw data would be fine. And reconciler
is even possible.
:component
and :ref
would help us a lot.
So, why do you want :component
? You have :refresh
and an arbitrary data mutation…so you hsould be able to change anything on the UI you need…or am I missing something?
Really what we want is the query and ident from :component
So we can use db->tree
/`tree->db`
But that’s not critical
I can put anything at all from the load request into the env
. The load marker is available and it has all of that. But there are two sets: the ident/query of the component that ran the load (which may or may not be present depending on how the load was triggered) and the keyword/ident + query of the load itself.
seems like making :ref
and :reconciler
be just like normal transactions (the triggering component’s), and perhaps drop the load marker bits into env under separate keys…perhaps as :load-request
I may start on that later tonight, so if there is any more feedback around it, please leave it here
Yeah that "recursive" call should work fine, but the second load stays in :fulcro/ready-to-load