@sineer it was more about displaying errors to user than validating
@baptiste-from-paris I investigated this before the announcement of Spec, so it is still based on Plumatic Schema, but there are some ideas here: https://github.com/plumatic/schema/issues/56
Thanks ! That's what I was talking about !
🙂 I would suggest doing something similar using Spec rather than going the Schema route
I added a new commit to my om.next/set-query! PR. I am aiming to support set-query! for datascript. https://github.com/omcljs/om/pull/857 Is this approach a good one and worth further work? Here is some illustration of the results. https://gist.github.com/sc13-bioinf/415b5bfd36b27d3a19b7f0d2ca88acda
@foobar I applaud the effort, I'd really like to see this feature.
I'm trying to see how it works, my immediate impression is that it's a lot of additional code. I was thinking more along the lines of an extensible interface.
?
I guess I saw it as a simple serialization/deserialization task but I'm not sure I understand everything involved.
Most of that is dealing with creating an index in which to store a query for each component. I didn't think that already existed (particularly for state that is not managed by om.next)
I could be wrong, I don't really understand om.next very well, hence asking if this is a good way to go, or the wrong tree to bark at
I though the index was stored on the app-state under :om.next/queries.
I haven't looked at that, I was only looking at the indexer, maybe I missed it
This line here: https://github.com/omcljs/om/pull/857/files#diff-ee424e6559581b5b893371373a777e5eR1312
I previously wanted to work on this and my idea was to replace swap! update-in
and get-in
with an API that could be implemented for different stores (and for the implementation to be kept outside of om core).
Didn't get any feedback on whether it was a good way to go so I never wrote any code, hope you get some.
As far as I can tell nothing reads from :om.next/queries at the moment
Yeah, you might be right there.
What benefits do you see from storing the queries on the app-state instead of the indexer?
I also thought that building a tree was important because I wanted to update one child and not its sibling. The parent would have to recognise that the queries of the children are now different.
The fact that you can persist the state somewhere and reload it I suppose.
E.g. in the gist, trunk begins with the static query for branch. Later on I modify the query for one of the branches
I would store the component queries in the indexer and not on the state. Simply because of the issue with the way its implemented at the moment and state that is not a map. Also it seems like a logical place for people to find this information.
There is also the possibility for people to pass their own implementations of the functions that build and query the index when using the indexer
Yeah, I wasn't sure. I like the idea of being able to persist/load the state and have everything exactly as it was. I'm not sure this is possible storing the queries on the indexer, unless you also persist the indexer separately.
I also wondered if there would be any advantages for the index to also be stored in app-state.
Doesn't that conflict with using set-query! ?
The way I understood set-query! at the moment was that it stored the queries in app-state...Although, like you said, I can't see where this information is actually used other than in merge!
.
I think you are right although I think a call to set-query when loading persisted state is reasonable
Yeah but you have to know what to call it with i.e. the params, which are lost unless you persisted the indexer or your code is written in such a way that it can work it out from the state.
Everything can be worked out from the state.
Params might be trickier I admit
In a way one could accomplish this without set-query by creating an anon component and building the appropriate query at runtime.
You can accomplish everything without set-query, it's just a nice pattern/convenience.
If you don't use set-query! you have to do some more magic in your parsers to extract the info from state and modify the ast/query.
(defmethod read :ui/dropdowns
[{:keys [state query ast user-parser] :as env} _ _]
(let [st @state
route (:compassus.core/route st)
keys (set (keys (select-keys components (route->components route))))
query (filterv #(contains? keys (ffirst %)) query)]
(println query)
{:value (assoc (user-parser env query) :route route)}))
(defmethod read :default
[{:keys [state ast query parser] :as env} key params]
(let [st @state
namespace (namespace key)]
(condp = namespace
"delegate"
{:value (parser env query)}
"remote"
(let [name-kw (keyword (name key))
val (get st name-kw)]
(println query)
{:api true
:value val})
{:value (get st key)})))
The print in ui/dropdowns gives a query like: [{:delegate/period-select [:start :end :ui/menus]} {:delegate/authors [:ui/menus]} {:delegate/category [:remote/advertisers :remote/categories :ui/menus]} {:delegate/created [:ui/menus]} {:delegate/inventory [:ui/menus]}]
Is there any way I can make the "remote" namespaced keywords trigger a remote query?
I'm using the convention that "delegate" namespaced keywords just recursively call the parser, as a way of nesting queries.
Wouldn't you have to send them to a read function that has those as its remotes? (also they have to be in the reconcilers list)
The remote is :api
and my default read function returns :api true
when the namespace is "remote"
So does it trigger your send function?
Nope, only if I add :api true
to the read response for "delegate" but I think then I need to use process-roots somehow to only send the remote keys.
Wouldn't :remote/something have to be a map key in order to trigger a read?
Im not sure what you mean. My query looks like:
[{:delegate/period-select [:start :end :ui/menus]} {:delegate/authors [:ui/menus]} {:delegate/category [:remote/advertisers :remote/categories :ui/menus]} {:delegate/created [:ui/menus]} {:delegate/inventory [:ui/menus]}]
I only want :remote/advertisers and :remote/categories sent to the backend.So, I upgraded om from 0.9.0 to 1.0.0-alpha48. Still only using om/core
no om.next
So :delegate/category triggers your default read and you pass [:remote/advertisers to the parser?
When I’m using om/build-all
I get the following warning in my console:
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `Constructor`. See <https://fb.me/react-warning-keys> for more information.
Shouldn't that be [{:remote/advertisers
(I am just guessing here tbh)
Supply a unique key for each li
@foobar: yes, but I would have thought that that would be the job of om/build-all
Since it already adds an index.
I don't know the details of build all but I am used to supplying keys 'by hand'
So, by redefining build-all
to
Yeah @foobar, I think my backend will handle it correctly as a property read or a join, not sure it matters.
Stuff works.
Its probably better if the key comes from your data though ?
@foobar: I could agree to that, but it kind’a makes build-all a bit useless, no?
@foobar how do you add the react-key to a dom/li
,
http://www.thesoftwaresimpleton.com/blog/2014/11/06/react-key/
LMGTFM 🙂
Something like that I think
Its just a guess, its a while since I used vanilla om
Ok, thanks, will try
(om/build-all dropdown-item settings {:key :text})
worked
@foobar Thanks a lot for your time!
I give up, I think i'm going to have to resort to a manual ajax request in DidMount and then a manual merge!
Wouldn't returning {:value something :remote/advertisers true :remote/categories} from "deletgate" trigger your send functions?
:remote/advertisers is not the name of the remote, it's just a property read.
I can trigger a send by returning {:api true}
from delegate but it isn't re-rooted and doesn't contain the actual keys I wanted for the backend.
I used the :remote/ namespace just so I could identify the keys intended for the remote and try to fiddle with the ast and re-root it somehow. Couldn't work it out though.
I think I can hack it by repeating the queries in my nested dropdown queries in the root component, so that the read triggered by the dropdown ends up being a local-only one.
Until I can get my head around it.
I'm using re-natal with om-next but whenever I call set-query!
with any class other than the root I get an error No queries exist for component path (fskl.ios.core/AppRoot fskl.ios.tabbar/TabBar)
. Any idea what I'm doing wrong?
(om/set-query!
(om/class->any reconciler fskl.ios.tabbar/TabBar)
{:params {:active-date (t/date-time 2017 3 10)}})))
Calling get-query manually works.
(om/get-query (om/class->any reconciler fskl.ios.core/AppRoot))
=> [{:app/budget [(:budget/by-date {:date #inst "2017-03-22"}) :date :amount]}
My queries look like this:
(defui ^:once AppRoot
static om/IQuery
(query [this]
(vec (om/get-query tabs/TabBar))))
(defui ^:once Budget
static om/Ident
(ident [this {:keys [date]}]
[:budget/by-date date])
static om/IQueryParams
(params [_]
{:active-date (t/at-midnight (t/now))})
static om/IQuery
(query [_]
'[(:budget/by-date {:date ?active-date}) :date :amount]))
@puppybits your Root component is stealing queries from the TabBar component
so there’s no clear path between the root and the children
that’s what the error message is telling you
anyone really using boot for om next development? I've managed to get things working with lein but, if I can, I'd like to figure out a workflow with om and boot. Am I just going against the current on this? Or does anyone know of any recent examples of this and a bit of hand holding on getting a good workflow set up?
@vaedasynapse setting up Boot with Om Next is no different than setting up with CLJS in general
can you clarify what you’re asking?