Well, at the moment the code is a little scatter-brained, and I'm not sure I can make it work for 100% of the intended use-cases, yet.
For one, I want to better support "collaborative" events -- for example, distinguishing drag-enter and drag-leave events requires tracking across multiple components. This requires coordination at the master component level which is currently missing. Additionally, as of 0.2.3, I'm noticing some effects from the differences between "render state" and out-of-render-loop states, which I'll need to account for. Those caveats aside: Here's the way it hangs together. Components are defined in one (or more) namespaces. Then there's the "ux" namespace, which is required by those wishing to get DnD features (and future "universal" features, such as "add item to selection") The Root component of the application calls (ux/setup-ux-master [app owner opts] ...) during will-mount. (ux/setup ...) creates some channels. One for putting drag-events onto, one for reporting bounds upwards, and a disperser (a mult over drag-events) so that we can direct drag events to interested listeners. When root om/builds sub-components, it just passes down the data that is created by ux in opts. Right now that's a bit hacky, but I hope I can alleviate some of that by using the new data locations (init-state, state, shared) in 0.2.3 When a sub-component is interested in receiving drag-events, it calls (ux/register [owner ... handler-fn] The handler function is for drag events that the sub-component is receiving. (Right now, this also reports bounds upwards, which I intend to separate out for readability/compos-ability) The neat part about keeping all this in the ux ns, is that we only need to look in the one file for where we're storing all this data (the channels etc). This makes changing any of that a little friendlier, and the components don't need to care (aside from having to call some functions in the right places) It also means I could potentially use ::qualified-keys for collision protection. (I plan on trying that out soon). ux/register finds the disperser multi-chan and taps it with a filter that only receives drag-events that are within the calling-components bounds, adding a (go..) loop with the handler-function it was passed in. The fact that every component controls it's own filter (via updating it's own :bounds on Did-Update) means we get targeted drag-events for "free". Unfortunately, we don't get drag-enter and -leave, which made me sad, because the current solution seems so elegant. The drag-start, drag-end, dragging functions are also in ux/ and are bound to the appropriate components with (om/bind ..) as usual. These update the local state of the owner where appropriate, and push an event on the command channel when "decision" states are hit (e.g. drag-end). I *could* create them with handler functions as parameters, but I figured I'd rather have a "command handler" at the Root component level to manage app-state. For me, I like having the logic of the components in the components, the logic of the application at the root level, and the logic of the orthogonal-user-interactivity in a separate namespace. Now, I have a specific application I was building this for - so this would need some work to be made truly "bolt-on". (there are assumptions about the names of refs, which'd have to be injected, for example). As an aside: In my application, the app-state revolves around a list of items. These items are displayed in multiple lists based on a filter, and sorted based on an attribute of the data. This means the "drop" handlers between the two lists simply set an attribute on the data, and React just puts them in the appropriate position of the relevant list in the next render pass automatically. On Thursday, January 23, 2014 1:52:58 PM UTC-8, David Nolen wrote: > It'd be a nice to get a detailed writeup about your approach if you have the > time and feel inclined :) > > > David > > > > On Thu, Jan 23, 2014 at 4:42 PM, David Pidcock <[email protected]> wrote: > > > On Thursday, January 23, 2014 10:13:49 AM UTC-8, David Nolen wrote: > > > Om's current API more or less follows this line of thinking - components > > are machines. However both the opaque nature of machines and the lack of > > fine grained control around immutable value storage (app state wrapped in > > an atom) have their downsides. I want Om components to have knobs. So while > > a component designer may decide to split their state in a certain fashion - > > users of the components should be able to reconfigure this without the > > system falling apart. > > > > > I am enjoying the ability to add behaviours to components via merging data > into local component state. It's quite handy when trying to achieve > orthogonal separation of concerns. > > > > For example - one might have several components on a page. Perhaps their > primary purpose is to display certain items in various ways. Perhaps you have > a group of items you want to split into different lists based on > classification rules. > > > > > One way to do this is to extend your sub-components, or to wrap them in a > bigger component that manages the communication between them. > > > > Using Om's opts, local-state, and shared, lets me put all the logic (and > inter-component communication necessary) for drag-n-drop into a separate > namespace, and then I can pull into the components the DnD behaviour, and > implement the few handler functions for the stuff that's specific to each > component's concern (e.g. mutate app-state on a drop). > > > > > Now, I've been dwelling in OO/Imperative land for a long time, so I'm sure > there are cooler ways to do all this.. but I'm having fun with it :D > > > > > > > > -- > > 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.
