Fantastic description.

On the Snackbar part though, have you thought about making it an 'effect' 
so you can send messages to it and subscribe to it (this pattern might make 
other things easier as well in elm-mdl)?

On Saturday, August 20, 2016 at 1:28:09 PM UTC-6, debois wrote:
>
> This is a great question! 
>
> Without internal state
>
> I think the most productive way of working with Elm is to avoid trying to 
> generalise and stick with expressing yourself directly in elm-lang/html 
> whenever possible. If you find yourself doing something a lot, use helper 
> functions to construct high-frequency pieces of `Html m`. Richards' answer 
> above is compatible with this philosophy. 
>
> You'll see elm-mdl take this route in a number of places, i.e., the Card, 
> Elevation, Footer, Grid, Lists and Typography modules contain just 
> functions constructing `Html a` values for you. You add behaviour as you 
> would anything in elm-lang/html by supplying your own attributes, typically 
> Html.Events.on*. 
>
> With internal state
>
> However, all the answers above make sense only if the Button you're 
> building doesn't have internal state. Let's say yours is a a fancy button 
> with animations; someone needs to track the current animation state of the 
> button, and update that state in response to DOM events. You now have just 
> two options for who that someone might be: (1) That someone is you: Stick 
> with working directly in elm-lang/html and manually integrate animation 
> logic for each button in your app's `Msg/update`. (2) That someone is a 
> component: Built a TEA component for your button. (If you think about it a 
> bit, you'll realise that if you don't like (1), whatever else you do, you 
> *must 
> *do the things TEA components do anyway.)
>
> Composing behaviours
>
> This choice brings us back to the original question: "How do I compose 
> behaviours in Elm"? If you go for (1),  "composing behaviours" is trivial, 
> because you didn't put up a wall in the shape of an API between your fancy 
> button and its surroundings; you just adjust the code from case to case as 
> you need. This emphatically *does not* mean that you now code by 
> cut-and-paste: As usual, when you find yourself doing the same thing in 
> different places, you factor out that thing into a helper function. As you 
> get more helper functions, perhaps a good API for a button component will 
> emerge.
>
> If you go for (2), full TEA component, "composing behaviours" is much, 
> much harder. You have to chose an API your button, and that API will 
> dictate exactly how it can and cannot interact with the rest of your app. 
> For a button, figuring out this API is maybe not that hard (maybe you can 
> set CSS on it, set its label, set its icon, and give it a Msg to fire when 
> clicked), but for even slightly more complex behaviours, I find producing 
> proper APIs surprisingly hard. A very large portion of the time spent on 
> elm-mdl went to devising APIs for seemingly simple components, like Cards, 
> Lists, and Badges. 
>
> The approach we took in elm-mdl was to mimic elm-lang/html as much as 
> possible: The only way to interact with a component is to customise it 
> through parameters to `view` (think `Attribute m`).  You "compose 
> behaviours" specifically by supplying `Msg`es you'd like to be sent in 
> response to internal events of the component. This approach is compatible 
> with the guidelines in Evan's sortableTable 
> <https://github.com/evancz/elm-sortable-table>. 
>
> In elm-mdl, we customise components only through parameters to `view` 
> because that's what elm-lang/html looks like. You could view it as a 
> ruthless, take-no-prisoners realisation of that guideline, though: When we 
> customise only in `view`, the component *cannot* store any of your data 
> in its model(*). 
>
> So, altogether, this is *my* preferred approach to "composing behaviour" 
> in elm:
>
> 1. Avoid components and work directly with `Html m` if possible. Avoid 
> repeating yourself by ample use of helper functions. "Composing behaviour" 
> is just producing `Html m` values. 
> 2. When you must make a component, let the Model of the component contain 
> *only* internal state of that component.
> 3. When you must make a component, "compose behaviour" with that component 
> by (a) telling it what to look like in `view` and (b) reacting to messages 
> it sends (back) to you. Never touch its Model. Never send it messages.
>
> This approach is not all-encompassing; I had to give up on (3) for the 
> Snackbar <https://debois.github.io/elm-mdl/#snackbar> component(**). For 
> UI components in general, though, I do think this approach is something to 
> strive for, and I do think it makes sense outside of elm-mdl. 
>
> Cheers,
>
> Søren
>
> (*) Almost can't. 
>
> (**) Snackbar holds a queue of messages to display. That queue has to live 
> in the model. The user can only add messages to the queue by messing with 
> the model or (actual choice) send messages to Snackbar. 
>
>

-- 
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