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.