Brilliant! Thanks a lot!

To summarise what I understood:

- A component should only update its internal states
- All updates of shared states should be done at a higher level
which could be further summarised in:
A state should only be updated by its owner (i.e. the highest component 
where that state appears) & no state should appear twice in the component 
chain.

There's just a slight glitch in your previous answer: WaypointConf is *not* 
100% synchronised: it needs its internal update to handle its hover state 
(for example, when hovering on a waypoint date date a button appears to 
open the corresponding date picker to modify it & the date picker has its 
own internal state such as hovering, open/closed etc.)
So while I do agree the slider can be reduced to a view, I don't think the 
WaypointConf can, which in turn means the Profile can't either.

Things get nasty when you try to synchronise shared states with internal 
ones, so don't do it (which, I think, is what you meant in a previous post 
with options 1 & 2).

A component can only operate on two kinds of states:
- states other components need to know: those are managed by a component 
higher up
- states others don't need to know: they should not depend on the previous 
ones & are managed by an internal update.

Am I on the path to enlightenment?



On Thursday, August 25, 2016 at 6:04:32 PM UTC+2, Richard Feldman wrote:
>
> Thanks! So let's start by talking about Slider for a sec.
>
>       SliderMsg (Slider.ChangeValue newSpeed) ->
>         { model | profile = newInternal, shared = Trip.setAverageSpeed 
> model.shared newSpeed }
>
> Because this code compiles, and it only covers the ChangeValue 
> constructor, then assuming speed is an Int, I can infer that Slider's Msg 
> looks like this:
>
> type Msg = ChangeValue Int
>
> A good question at this point is: *how much of Slider's state must be 
> synchronized *with other state in the application?
>
> For example, if Slider had some sort of visual flourish like "every time 
> you drag it, it changes color," that state would not need any 
> synchronization with other parts of the app. The slider would change color 
> when you dragged it, and the rest of the application would neither know nor 
> care.
>
> The Slider's value is not independent like this. If you put a slider on a 
> page and its value changes, but no other code ever finds out that its value 
> changed, then the slider is useless! Its value needs to be synchronized 
> with other state in order to be useful.
>
> Since Slider has no other state besides this value, then Slider's state is 
> *100% 
> synchronized* with other state. In a case like this, you have two options 
> for keeping it in synchronized:
>
> 1. Give Slider its own Msg, and translate between its Msg and its caller's 
> Msg
> 2. Do not give Slider its own Msg, just have its view accept a Msg 
> *constructor* as an argument.
>
> The second option is simpler. Here's how that would look:
>
>
> viewSlider : (value -> msg) -> value -> Html msg
>
>
> Now we can change Profile's Msg to this:
>
> type Msg =
>   WaypointConfMsg Int WaypointConf.Msg
>   | *SetSpeed Int*
>
>
> ...and render the slider like this:
>
> viewSlider SetSpeed currentSpeed
>
> So now Slider no longer has its own Msg, it just says "hey caller, tell me 
> how to wrap my values in your Msg type, whatever that might be, and we're 
> cool." Now instead of Slider being a Model, a Msg, an update, and a 
> view...it's just a view! :)
>
> Let's look at Waypoint next:
>
> WaypointConfMsg idx msg' ->
>         case msg' of
>           WaypointConf.ChangeDateOrTime _ ->
>             { model | profile = newInternal, shared = Trip.changeOpDate 
> model.shared idx <| getDate idx model newInternal }
>           WaypointConf.SameDateAndTime _ ->
>             { model | profile = newInternal }
>
> Like Slider, its state is still *100% synchronized*, meaning it also 
> doesn't need its own Msg. We can convert Waypoint into a view function 
> (which accepts a "here's how to wrap things as a Msg" function just like 
> Slider did—or maybe two of those functions, since there are two things 
> Waypoint can change), at which point we no longer need a Waypoint Msg, 
> Model, or update. Only a view.
>
> Finally, since Profile only has Waypoint and Slider inside it, and since 
> Profile has no independent state to track either, we can give it exactly 
> the same treatment as what we did for Waypoint and Slider.
>
> To summarize how I'd recommend organizing things:
>
>
> *Current*
>
> WaypointConf - Model, Msg, update, view
> Slider - Model, Msg, update, view
>
> Profile - Model, Msg, update, view
>
> App - Model, Msg, update, view
>
>
> *Proposed*
>
> WaypointConf - view
> Slider - view
> Profile - view
>
> App - Model, Msg, update, view
>
>
> Hope that helps! :)
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to