You can use swap! directly, but doing so will lose some of what Om gives
you (like :tx-listen) and therefore is somewhat discouraged.

You can pass cursors around and transact on them even outside of an Om
component (but remember that if you are not in the render phase you must
use @cursor to read its value).

What I personally do is have an invisible root component which is
responsible for managing various things such as which "page" component is
visible and transacting on the root app-state. This design would likely
work for you.

How I'm structuring my app is that all non-local user actions are put on a
channel. These sound exactly like what you use: [id data] and I use
(async/pub ch first) and then I can subscribe to different action ids. All
of my event handlers simply put to this channel and I have helpers that
subscribe (using om-tools mixins so that they auto-unsubscribe on unmount)
to event ids putting the event data into component local state. Something
like this (not my actual code):

(reify
  om/IInitState
  (init-state [_]
    {:x "Not Clicked"})

  om/IWillMount
  (will-mount [_]
    (.subscribe owner :foo [:x]))

  om/IRenderState
  (render-state [_ {:eys [x]}]
    (dom/div #js {:onClick (async/put! my-dispatch-ch [:foo "clicked"])}
      x)))

This way I can send non-domain-data update messages to components in a
clean and consistent way. Any domain data updates are handled in my
invisible root component (which then transacts on the app-state).

However, I do use cursors to update app-state in a component if the change
is entirely encapsulated in the component. For example, if I have a
component that displays a list and clicking on a list item deletes the
entry, then that components can transact on the list directly to make the
change.
My logic for this is that if a component can be made completely self
contained, then it should be. Aids reusability and makes the code clearer.
But if components need non-local knowledge then the logic is pulled out and
handled externally (by the invisible root component).

I've found this to work quite well so far. I will blog about it sometime
when I have some more time.


On 8 October 2014 13:30, Nikolas Göbel <[email protected]> wrote:

> Hey everyone,
>
> I've started experimenting with ClojureScript + OM for a rewrite of a
> medium-sized Web-App. I started in PlainJS + React/Flux but quickly found
> myself hacking together things already available in ClJS, so now I'm here.
>
> May I ask for some feedback on the architecture im planning? Especially if
> I'm missing/violating any established practices:
>
> As in Flux, I plan to establish a single core.async channel on which every
> action the user triggers is published as some kind of tagged event. My
> first idea was to have components in the hierarchy subscribe to different
> tags, depending on their level of knowledge. A top-level component would
> then carry out the actual app-state transaction. This is a variation of the
> channel based communication shown in the Basic Tutorial[1] except that my
> approach would rely on a single shared channel and tagged events, instead
> of different channels for each purpose.
>
> Thinking further about the problem I came to the conclusion that
> separating transaction handling from the component hierarchy would be much
> more desirable.
> My rationale for this is that having components update the app-state kind
> of breaks the unidirectional flow paradigm. Also, I would prefer to have
> all logical interactions of the UI abstracted away, such that it becomes
> reusable (maybe for mobile applications).
>
> Flux kind of solves this by intertwining Stores with update logic (which
> is ok I guess, but not possible with an atom). I figured that in CLJS I
> would simply subscribe functions to the dispatcher channel and have them
> transact the app-state atom.
>
> Since I can't om/transact! on the atom directly, I would like to know if
> there is a way to pass cursors / create new cursors outside of the
> component hierarchy? Or can I use swap! instead? Would I be losing anything
> more than the tx-chan observability (which I really don't want to lose...)?
>
> Thank you and please feel free to completely tear apart any of this if it
> doesn't make sense in CLJS world (which I'm rather new to).
>
>
> [1] -
> https://github.com/swannodette/om/wiki/Basic-Tutorial#intercomponent-communication
>
> --
> 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.
>

-- 
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.

Reply via email to