Yes, that is a valid reduction. Specifically my register-handler,
which only has access to db needs to know the result of f.

The general principle of having my register-sub delegating to a defn
which is called from the register-handler is causing the pain because
there is actually a hierarchy of subscriptions going on here, so the
value of f might actually be resolving a chain of subscriptions. For a
simplified example:

(register-sub :reference-data/locations)
(register-sub :reference-data/active-locations .. (reaction (subscribe
[:reference-data/locations))))
(register-sub :page-1/location .. (reaction (if (following-defaults?
(-> db ...) @(subscribe [:reference-data/active-locations))))

the value of :page-1/location is of interest.


On 21 April 2015 at 14:27, Mike Thompson <[email protected]> wrote:
> On Tuesday, April 21, 2015 at 10:58:31 PM UTC+10, Colin Yates wrote:
>> Hi Mike - yeah, reading through I wasn't very clear. Let me try again
>> with a more fleshed out example:
>>
>> On the server there is a hierarchy, each node in that hierarchy may
>> contain some meta data for example:
>>  :id - the unique id of the node
>>  :type - indicating some semantics about that particular node
>>  :current? - indicating whether it is still actively used or not
>>
>> Imagine there are 5 nodes and node 4, which is a leaf is not :current?.
>>
>> On the client I have a number of projections of this data:
>>  - an "active" tree which prunes out all nodes that aren't :current?,
>> so there are 4 nodes
>>  - an "everything" tree which shows everything, e.g. all 5 nodes
>>
>> In addition, every node in each tree is selected and there are
>> multiple instances of these trees.
>>
>> On the client (on a reporting page for example, where one of these
>> trees are in the filter) I need to know which nodes the user has been
>> selected. I have a handler, which in response to some event (either
>> the server indicating new data is available or the user changing some
>> data) which needs to know which nodes have been selected.
>>
>> If the user hasn't selected anything then the 'selected nodes' should
>> be the default set (i.e. all of the nodes). As soon as the user
>> changes the selection (by deselecting a node in the first instance)
>> the set of selected nodes is now every node that is selected (e.g.
>> every node apart from the one they just selected) and that instance of
>> the tree is no longer tracking the defaults.
>>
>> The server is free to send new config data at any point in time. When
>> this happens, the default set should be updated. The non-default set
>> that the user has changed should also be consolidated as well, but
>> that is different.
>>
>> Lets say my app state looks like:
>>
>> {:page-1 {:some-active-tree {:selected-ids [] :tracking-default? true}
>>                 :another-active-tree {:selected-ids [] :tracking-default? 
>> true}
>>                 :some-all-tree {:selected-ids [] :tracking-default? true}}
>>
>> The user hasn't done anything so the selected-ids should be the
>> default sets (4 ids for :some-active-tree and :another-active-tree and
>> 5 ids for :some-all-tree). If the user were now to deselect node 2 in
>> :another-active-tree then app-state looks like:
>>
>> {:page-1 {:some-active-tree {:selected-ids [] :tracking-default? true}
>>                 :another-active-tree {:selected-ids [0 1 3]
>> :tracking-default? false}
>>                 :some-other-tree {:selected-ids [] :tracking-default? true}}
>>
>> If they deselect node 3 in some-other-tree:
>>
>> {:page-1 {:some-active-tree {:selected-ids [] :tracking-default? true}
>>                 :another-active-tree {:selected-ids [0 1 3]
>> :tracking-default? false}
>>                 :some-other-tree {:selected-ids [0 1 2 4]
>> :tracking-default? false}}
>>
>> Should the server now update the config hierarchy changing node 4 back
>> to :current? and adding another node then at the very least the
>> 'selected nodes' for :some-active-tree should contain the ids of all 6
>> nodes.  :another-active-tree and :some-other-tree should also be
>> informed but they might not be updated depending upon the selections
>> (it gets more complicated...).
>>
>> At this point it is clear that one solution is to record a delta from
>> the defaults, but that only works because we are talking about
>> booleans; there are other non-boolean use-cases unfortunately.
>>
>> Another solution is to store the sets of defaults in app-state itself
>> rather than have it be a subscription and then overtime it changes
>> update the affected parts of app-state (:some-tree and
>> :some-other-tree in this example).
>>
>> This would be much easier if it was just dealing with rendering data,
>> in which case subscriptions are a perfect fit, but the set of data
>> needs to be sent back to the server periodically in a handler, and
>> handlers can't see subscriptions.
>>
>> To be frank, if anyone is still reading, my experience tells me that
>> if the problem is this hard to explain and requires this much
>> explanation then _I_ haven't understood it properly :), so I think I
>> need some more hammock time is in order.
>>
>> Thanks for anybody who hasn't lost the will to live yet ... :).
>>
>> On 21 April 2015 at 13:08, Mike Thompson <[email protected]> wrote:
>> > On Tuesday, April 21, 2015 at 4:52:05 AM UTC+10, Colin Yates wrote:
>> >> Hi,
>> >>
>> >> This is somewhat reframe specific, but how do people handle 
>> >> default-values that can change? My specific use-case is that I have a 
>> >> tree which can be expanded and collapsed. By default the tree should be 
>> >> expanded to a certain level, however, as soon as the user manually 
>> >> expands or collapses a node they should no longer follow the default. The 
>> >> data the tree is displaying can change, meaning the defaults can change 
>> >> over time.
>> >>
>> >> I can't simply define the defaults on startup because the defaults will 
>> >> change over time.
>> >>
>> >> It can't be a subscription because the values need to be available in the 
>> >> handler.
>> >>
>> >> My current thinking is that the app-db state has a 'follow-defaults?' 
>> >> which is true by default but is set to false when the user explicitly 
>> >> changes the state (e.g. by expanding or collapsing). When the underlying 
>> >> hierarchy changes from the server, propagate that change to all of the 
>> >> parts of the app-state that are interested.
>> >>
>> >> To be explicit, imagine I have the following template for tree: 
>> >> {:expanded-ids [] :follow-defaults? true}. There are 6 instances of this 
>> >> template in the app-db  (i.e. 6 distinct UI trees). When the server 
>> >> informs the client that the source-data has changed it then updates each 
>> >> instance where follow-defaults?.
>> >>
>> >> I understand the rationale as to why subscriptions can't be in the 
>> >> handlers but a subscription which switches on follow-defaults? seems 
>> >> ideal.
>> >>
>> >> Maybe I could hack a UI-less component which reacts to that subscription 
>> >> change by directly updating the underlying db...
>> >>
>> >> What would you all do?
>> >
>> >
>> > Hi Colin,
>> >
>> > I'm not sure I'm clear on the problem. Here's my attempt to explain back 
>> > ...
>> >
>> > You have some setting (data) in your app (tree display state) which can be:
>> >    1. in a server-supplied state (you call this "default" state?)
>> >    2. optionally, in user-supplied state (if present, overrides 1).
>> >
>> > Over time, new versions of 1. arrive.  If 2. exists, it always overrides 1.
>> >
>> > Have I understood?
>> >
>> > --
>> > Mike
>
>
> Hmm.  I don't get the specifics, but maybe we can talk abstractly ...
>
> You have values a and b which can change over time. And you have another 
> value c which is a function (f) of a and b.
>
>      (f a b) => c
>
> And, a b and c are all stored in `app-db`.
>
> And then when, say, 'a' gets updated (server?  user?), you want to 
> (reactively) modify the value in c again.  After all, its value is a function 
> of a and b, and a just changed?
>
> And you are reaching for `subscribe` as a way to sorta know when to rerun 'f' 
> to recalculate new 'c'.
>
> Have I got it now?
>
> --
> Mike
>
>
>
>
>
>
> --
> 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