If it helps, I have a 'state' namespace with the global state and some
global cursors and then a separate .view.X namespace for each 'page'.
Each page has a consistent API including 'visible?' and 'id' which a
main namespace bootstraps. It bootstraps each page by checking if it
is visible? and if so passing in a sub-cursor of ((:id page)
app-state).
Main depends on state and each view. Each view (sorry, 'page') is
self-contained but may depend on state. For global application wide
things like reference-data etc. I have utility functions in main which
depends on sente plumbing.
(ns my-app.state
(def app-state (atom {}))
(defn some-reference-data [owner] ....)
(ns my-app.main
(require [my-app.view.page1] [my-app.view.page2] [my-app.view.page3] ...)
(ns my-app.page.view1)
(ns my-app.page.view2
(require [my-app.state :refer [some-reference-data])
(ns my-app.page.view3)
(anyone know of a way to load all namespaces to pick up defmethods etc.?)
The whole app tends to co-ordinate around app-state and I have found
surprisingly little need to communicate between pages, or even
components outside of app-state.
Each 'page' is both the view and the controller with the app-state
being the model. Communication between pages is minimal and done via
app-state if ever. It is all simple and works for me. I can think of a
thousand use-cases where this would turn into a spaghetti-ball but
haven't run into them yet.
Hope this helps, and as this is my first om and ClojureScript app take
a handful of salt with my advice :).
On 23 February 2015 at 19:16, Alan MacDougall <[email protected]> wrote:
> tl;dr I want to restructure
> https://github.com/amacdougall/alpha-counter/blob/master/src/alpha_counter/core.cljs
> to separate views and logic, but the views refer to functions and data which
> do not belong in the same namespace as views. If the views namespace requires
> core, and the core namespace requires views, a) the CLJS compiler doesn't
> like it and b) my design is flawed anyway. Unfortunately, none of the usual
> remedies seem like improvements.
>
> Longer explanation:
>
> Right now, I have a simple Om webapp with data, views, and domain logic in
> the same namespace. It is structured a bit like this:
>
> (ns example.core)
>
> (def useful-constant ...)
> (def list-of-constants [...])
>
> (defonce app-state ...)
>
> (defn domain-logic [cursor flag] ...)
>
> (defn sub-view [cursor owner]
> (reify
> om/IRender
> (render [_]
> (dom/button {:onClick #(domain-logic cursor :flag)}))))
>
> (defn main-view [app owner]
> (reify
> om/IRender
> (render [_]
> ...)))
>
> (defn main []
> (om/root main-view app-state {:target ...}))
>
> Now, I want to separate the application into namespaces. It seems reasonable
> to split out a separate example.views namespace, so we would have something
> more like this:
>
> (ns example.core
> (:require [example.views :as views]))
>
> (def useful-constant ...)
> (def list-of-constants [...])
>
> (defonce app-state ...)
>
> (defn domain-logic [cursor flag] ...)
>
> (defn main []
> (om/root views/main-view app-state {:target ...}))
>
> ;; and...
> (ns example.views
> (:require [example.core :as core]))
>
> (defn sub-view [cursor owner]
> (reify
> om/IRender
> (render [_]
> (dom/button {:onClick #(core/domain-logic cursor :flag)}))))
>
> (defn main-view [app owner]
> (reify
> om/IRender
> (render [_]
> ...)))
>
> Obviously this fails, because namespace requirements cannot include cycles.
> The usual answer is to provide functions to the views as props, but this
> would mean something like this:
>
> (defn main []
> (om/root views/main-view
> {:app app-state
> :fn-1 fn-1
> :fn-2 fn-2
> ...}
> {:target ...}))
>
> And then we'd have to laboriously pass each function down through the
> component tree until it reaches the component which uses it.
>
> Another solution would be to move the domain logic functions (and constants
> and whatnot) into a namespace of their own, which can be required by the core
> and views namespaces; but then it seems strange for the core namespace to
> exist only for the purpose of booting up the main view. And what would I call
> the new namespace? "domain"? "logic"? "everything-that-is-not-a-view"? If it
> is not obvious how to name something, it suggests that it should not be a
> separate entity to begin with.
>
> I have a feeling that I'm fundamentally confused about something, but I am
> too ignorant even to know what. Any advice would help.
>
> The actual webapp in question is
> https://github.com/amacdougall/alpha-counter/tree/master/src/alpha_counter,
> if you're curious.
>
> --
> 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.