My feeling is that your app-state atom should contain everything that would be saved into a document if your user did a File->Save in a conventional desktop application. Given that, it wouldn't seem appropriate to put things like channels or flags for tracking mouse/hover state and that sort of thing into the app-state atom. I feel that that sort of thing should live in component local state. I agree that things get a bit trickier in the case you outlined with the 'current-cat' example. You can pass multiple cursors to a component (https://github.com/swannodette/om/wiki/Cursors), so the cat-viewer component could rely on two cursors: one cursor to the list of kitties, and another to the :cat-viewer-widget entry which would allow it to transact! directly on the app state and set the current cat itself.
An alternative approach is to have the cat-viewer-widget just pass an event on a channel when someone selects a cat. A parent component would then be responsible for pulling this event off the channel and transacting! on the app state to set the current cat. In my project, I have the exact same situation, except I'm displaying and selecting colors instead of cats (https://github.com/jackschaedler/goya/blob/master/src/cljs/goya/appstate.cljs See :palette and :paint-color). I've decided to go with the second option, creating a parent component which has a cursor to basically the entire application state (which is less than ideal), and this component builds a child component whose job is to render the list of colors and pass any clicks/selections on those colors to the parent component via an async channel: https://github.com/jackschaedler/goya/blob/master/src/cljs/goya/components/palette.cljs#L18 The parent component is then responsible for transacting! on the app-state - It's acting sort of like a controller for all child components, waiting for children to send events or requests over the channels it created in its component local state. As for the 'should you transact! or let someone else do it for you' question, I think that just needs to be worked out on a case by case basis. I've mixed and matched a bit, and I don't see any benefit to letting another component transact! on your behalf if you can do it via your own cursor (https://github.com/jackschaedler/goya/blob/master/src/cljs/goya/components/canvastools.cljs#L26) Those are my very un-informed two cents coming from a complete beginner :) Hopefully that's somehow helpful! On Friday, May 2, 2014 7:32:40 AM UTC+2, Elliot Block wrote: > There seems to be a few types of shared state in an Om system: > > 1. "model"-ish data, e.g. if your app's about cats, a list of cats. > 2. "view"-ish data, like whether a given UI panel is shown or hidden > 3. coordination-ish data, like async channels so that components can talk to > each other, e.g. to show or hide panels, to switch the cat being displayed. > > Which one or more of these is supposed to go in the global app-state atom? > > Suppose that you put both model and view state in the app-state atom: > > (def app-state > (atom {:cats {"Fluffy" {:age 7} > "Scratchy" {:age 5}} > :cat-viewer-widget {:current-cat "Fluffy"}})) > > How do you provide a cursor to the cat viewer widget without giving it a > completely global cursor, or without hopelessly intermixing the model and > view data? > > Alternatively, suppose that only the "model" data lives in `app-state` atom. > Presumably then the view state is component-local, but then that just implies > you need a globally addressable async channel to talk to it. Where does one > put the async channels so that other components can talk to them? Options > include: > > - Include channels in `app-state` atom > - :shared global component state > - Some other var in scope in the namespace > > (This also raises the question of, when you should prefer to om/transact! > directly vs. use a channel to ask some other process to transact! for you? > But I'll leave that one for now.) > > Haven't been able to find a write-up on this in the past few days. Any > guidance greatly appreciated. Thank you! > > - Elliot -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/clojurescript.
