This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-05-12
Channels
- # admin-announcements (1)
- # aleph (1)
- # arachne (10)
- # beginners (6)
- # boot (81)
- # braveandtrue (3)
- # cider (42)
- # cljs-dev (1)
- # cljs-edn (52)
- # cljsjs (9)
- # cljsrn (9)
- # clojure (62)
- # clojure-austin (1)
- # clojure-belgium (11)
- # clojure-berlin (2)
- # clojure-gamedev (2)
- # clojure-greece (1)
- # clojure-russia (73)
- # clojure-uk (98)
- # clojurescript (156)
- # community-development (4)
- # component (3)
- # cursive (30)
- # datascript (10)
- # datomic (17)
- # emacs (5)
- # events (1)
- # hoplon (315)
- # jobs (1)
- # jobs-discuss (3)
- # lein-figwheel (6)
- # luminus (18)
- # off-topic (13)
- # om (130)
- # other-languages (122)
- # re-frame (32)
- # reagent (27)
- # rethinkdb (6)
- # ring (2)
- # ring-swagger (31)
- # spacemacs (4)
- # untangled (6)
- # yada (30)
Figured it out
(defn test-ajax [state owner input]
(go
(let [access-token (get-in state state/user-access-token-path)
api-result (<! (ajax/managed-ajax
:get
(api-url (str "/api/v3/users?per_page=5&search=" input))
:headers {"Authorization" (str "Bearer " access-token)}))]
(om/update-state! owner :options (fn [v] (distinct (concat v (:resp api-result))))))))
Thanks to some help from @cjmurphy I was able to start to get some things together on this gist: https://gist.github.com/mattyulrich/8524ce8f20606e644770205021875639
I’m facing a new problem, when my data has a single element, the om/db->tree function appropriately pulls out the requisite element.
But when my data is a vector (eg. from gist - :classes
or the :students
data within the :selected-class
), I end up with a vector of empty elements..
:selected-class
resolves to {:class-id 1, :class-name Learning Om, :teacher {:user-id 456, :user-name Fred}, :students [{} {}]}
:classes
resolves to [{:teacher {}, :students {}} {:teacher {}, :students {}}]
Yeah - sorry, I did that to pass the :current-user
straight from the App-Content (root):
(header-component current-user)
While those semantics may be funny, that bit seems to be working fine.
(there is an exception to this - when a different component needs the same data, I believe).
Passing the props straight through is usually a bad idea:
(app-class-list-component (om/props this))
Another thing I do to stay out of trouble is put idents in everything. In the app state I just have a single number for say a panel or whatever.
I just looked through the Kanban demo and every single time a component has a query it also has an ident. So it is a good rule. Without idents Om Next won't know what to do with joins.
Ok.. that’s something worth investigating..
And you need joins to separate out your queries/components. It is obvious to do a join in 1:M case. But joins are good for 1:1 as well.
I did find that kanban demo very instructive; it certainly got me where I am now; thanks for that.
So - I just put some output from my REPL in a gist to demonstrate the specific issue: https://gist.github.com/mattyulrich/95cea7cbbf60520cbdc8e6a7ffcb9fd9
Do you think this type of result from the om/db->tree
call at the end is likely due to missing idents and joins?
It resolves teacher just fine but not the students
But teacher is a single user, students is a vector of users
I don't have much experience of not using idents for everything, and not having state always in default db format.
I would guess that db->tree can work fine just on the data, as long as it is in default db format.
Ok, and that format is the one I get from the tree->db call; right?
Yeah - I’m not explicitly doing it in my code; I just did it at the REPL there to demonstrate how my current set of Idents/Queries is restructuring the initial app state.
Are there all idents in your state i.e. is it fully normalized? Perhaps it is because your state is all 'data' - your components are not also making it into the state.
Except for the three main root components, :current-user, :selected-class and :classes
Those refer to the idents.
I thought I may have been missing something because it seems like my read functions can get the data for the single idents just fine, but the vector of idents is coming up empty… I wasn’t sure if there was something special I needed to indicate in my query semantics to say “this should be a vector”..
But, maybe I should just try and be more rigorous with Idents and Joins as you describe and see what happens.
I’ll give that a shot and see if I can get more color on what’s going on.. Thanks again for the help with this, I’ve just been trying to get my head around how this all works - quite a learning curve on it.
I don't like fact that :students
is not coming in from the root, as a join query to Class-User
.
Meaning you think it should be there?
Ok… so in the root app query (App-Content) you think there should be a “:students” join leveraging the Class-User query...
in the REPL?
Ok - lemme see if I can try cleaning this up a bit more; add more Idents and push these queries up to the root...
In general, when trying to use Om.next, I’m finding myself more and more structuring my UI to conform to my data…
yeah - I can sometimes see shadows of how this is powerful, but it often seems like data & ui acrobatics to just get something to show up...
I keep telling myself that I just don’t understand, or that it’s just some confusion in syntax or semantics - but the more I figure out, the more I feel like I don’t understand...
Anyway, this little example app emerged out of trying to simplify a bigger and more complicated app to better understand - as such, it has gone through evolutions of confusion and understanding; I’ll take some time to make it more readable and a smaller problem to see if I can work up from these smaller building blocks.
I called you out at the beginning of this just to give credit for getting me where I am now; didn’t mean to rope you into further assistance. Thanks again for taking a look and providing some guidance and suggestions.
Some feeling of disconnect - like just learn the rule and worry about understanding it more deeply later. A nice book would be good - but it is early days yet. I really like it as your app starts to get bigger and bigger. Was at a pause so a bit of roping in good 🙂
FYI - I just figured out the problem above; I was wrapping my initial app state in an atom explicitly rather than passing it to the reconciler as a value. Once I took out the atom, everything worked.
Does this mean that when the reconciler :state
is passed as an atom, it assumes the data is already in the db format and doesn’t internally restructure it?
@mattyulrich: from Om Next’s documentation:
:state - the application state. If not an atom the reconciler will normalize the data with the query supplied by the root component.
https://github.com/omcljs/om/wiki/Documentation-%28om.next%29#reconciler-1Ok - yeah, missed that bit when setting up my app. Thanks.
I’m trying to get a ref to an ident (from my select) - I see get-ident
- given a component, return its ident; is there a way that given the ident value (ie. “2”) and the ident key, I can lookup the ref for that ident?
@mattyulrich: not sure what you mean by the ref
, but there’s ref->component
, where given an ident
it returns the component that matches that ident
?
I’m probably going about this all wrong; trying to wire up a dom/select
- in the onChange
event, I want to mutate some state and set the ident associated with the selected option. I can get the “value” of that option from the event, but that’s currently just a number, the ident value.
@mattyulrich: so you might not want to rely on the event information for that. can’t you pass the ident
of the thing you’re mutating to the transact!
call?
Maybe I haven’t seen the right example yet; not sure the best way to use a dom/select
in om.next.
I guess my real question is: how do I get the ident of my option out of the select onChange event?
Or is there a better event to be using?
@mattyulrich: I’m not quite sure that you’re options need to have idents
in any case, get-ident
is a thing
if you’re calling transact!
inside the option component
Well, maybe I structured it wrong. I have a select with a list of classes (option value: class-id), when I select one I want to transact the current selected-class to the one chosen in the option.
I’ll try and clean up what I have and update my gist.
does shouldComponentUpdate
return true if only computed data changes? I’m having a hard time deciphering the macro, but it in my experience it returns false if props and state are the same while computed is different. wondering if that’s on purpose or not
@dnolen: I’ve been digging into the problem with instrumentation
@anmonteiro: any luck?
The solution I initially thought about can’t work
because it creates infinite loops
which is pretty much something you know already, and the reason behind build*
in om.core
my thinking now is that we need some kind of factory function that can’t be intercepted by instrument
@dnolen: or introducing another option to factory
, a boolean instrument
value, which we call with false
inside the instrumentation function, to prevent loops
@anmonteiro: ah right
@dnolen: I’ve got it working like that, I’ll submit a PR to see if you agree with the implementation choice
@dnolen: PR submitted: https://github.com/omcljs/om/pull/681
@hueyp: computed is just a prop, but when you call om/props
it doesn’t actually give you the computed map
so if the macro is checking om/props
as opposed to React props, it might be missing it
which, looking back at the macro, is exactly what’s happening — a call to om/props, and a check that the props are an instance of OmProps
I think this is a bug
albeit a minor one
@ethangracer: I’m pretty sure that computed props weigh in on the sCU decision
here it happens too: https://github.com/omcljs/om/blob/master/src/main/om/next.cljs#L1729
I wonder what’s the particular use case where this is causing you problems
my understanding would be that: - if you’re passing callbacks they won’t really be changing - any other stuff might influence rendering, so it’s a good idea for it to be a part of the decision
@anmonteiro: did this change as of alpha-33? I’m on 32, and I’m not seeing the reshape-map
where shouldComponentUpdate was previously defined
nor am I seeing the shouldUpdate?
function you referenced on 1729
and yes, the callbacks aren’t changing. what I’m currently doing is passing a search string down through components to help filter what components are shown — nothing else is changing, but I still need a re-render triggered. for now I just overrode the function in my defui and have it return true...
@ethangracer: I don’t understand your question
reshape-map
is only ever seen by the JVM in macro expansion
right, isn’t that were the defui’s shouldComponentUpdate is defined?
I understand it’s a macro, but it gets expanded when defining the component in cljs, doesn’t it?
yea, what defui
does is create a component constructor and attach those functions to its prototype
right
and it seems that the definition of shouldComponentUpdate in there may be missing computed
ok I found should-update?
— even there, computed is pulled out before the call to should-update?
, but is never passed anywhere
(when (mounted? c)
(let [computed (get-computed (props c))
next-props (om.next/computed (ui->props env c) computed)]
(when (should-update? c next-props (get-state c))
(if-not (nil? next-props)
(update-component! c next-props)
(.forceUpdate c)))))
nevermind, I see it now
I don’t know, it seems not to work
@ethangracer: Ah, I know what you mean
and it’s related to the OmProps
check
yeah, what is that?
nested components receive that deftype
instance
the top level component doesn't
it’s just a wrapper for Om’s props
thing is computed
should be in there too
I would think so too. All I know is that on alpha-32, if you set up a parent component to update it’s state based on text being entered in a field, and then you pass that data through computed to a child component, the child only re-renders on the first change to computed. then it stops
@ethangracer: happy to look at a minimal case
could definitely be that I’m doing something else, but figured I’d throw it out there because my testing indicates otherwise
yeah let me work one up, i’ll send it your way
thanks
@anmonteiro: changing computed does seem to trigger a re-render for a simple app, just not confident that I’m recreating the same scenario. I’ll keep playing around and let you know if I figure it out
Ok - I’ve updated my gist with my problem: https://gist.github.com/mattyulrich/8524ce8f20606e644770205021875639
At line 140, how could I get the ident of my option? Or, is there a better way to approach this whole select
thing?
I guess the big problem is how to I move between the synthetic events of the om/dom components and the om components?
Or should I just eschew those events in favor of another approach?