gampleman / elm-examples-helper / Example

This module is designed to make certain kinds of example easier to understand by ommitting some of the boring details and yet making them attractive. You can get creative with it if you want:

module MyExample exposing (main)

import Example as OmittedForBrevity

view model =
    case model of
        Loading ->
            OmmitedForBrevity.loading

HTTP

If your example is doing an HTTP request, Elm will force you to handle some states like what to show when the request is in progress and what happens when it fails. However, your example might be about the "happy path" and everything else is just noise. Here we provide some helper views to show something nicer than Html.text "Loading...", but help keep the focus on what's important.

loading : List (Html.Attribute msg) -> Html msg

Displays an animated loading spinner indicating an operation is in progress.

error : Maybe msg -> Http.Error -> Html msg

Shows a friendly (albeit generic) error message based on the HTTP.Error type. Useful for showing when an HTTP request fails.

You can optionally give it a message. If you do, then certain errror will get a "Try again?" button for retrying the request.

Configurable Views

A common type of example is trying to demonstrate something that happens in a view. Maybe your example is rendering a cool fractal or 3D scene or just a neat way to render a HTML table. Often such functions can be customised by the user with various parameters. The functions here help you with minimal fuss make your view function interactive:

module MyExample exposing (main)

import Example

type alias Model = -- this is your configuration
    { foo : Int
    }


view : Model -> Html msg
view model =
    -- do whatever you want here, this your example
    ...


main : Example.Program Model
main =
    Example.configuration
        { foo = 3 } -- this is your default or initial model
        -- here you configure your form
        [ Example.intSlider "Foo count" 0 5 .foo (\value model -> {model | foo = value})]
        |> Example.withTitle "My cool example" -- you can customize with options
        |> Example.application view -- Connect it to your view

This gives you a number of built in behaviors:

application : (model -> Html (ConfigMsg model)) -> Configuration model -> Program model

Start an application based on a view (this is your example) and a Configuration.


type alias Program model =
Platform.Program () (Model model) (ConfigMsg model)

This is a type alias for Program, mostly useful for type annotations, as not using the type alias exposes too many implementation details of how this module is implemented.

I recommend using it prefixed:

main : Example.Program Model


type Configuration model

All the details needed to make an example app get stored in here.

tabbed : String -> List ( String, model ) -> Configuration model

This is the most simple example app, where you want to switch between a discrete set of pre-made configurations.

You need to provide a form label, and a list of labels and possible models.

configuration : model -> List (Field model) -> Configuration model

This is the more flexible way of building example configurations. You will need to provide an initial model which is what users will see before they mess with the forms.

Then you need to provide some fields that will show as the form.

Building forms


type Field model

intSlider : String -> { min : Basics.Int, max : Basics.Int } -> (model -> Basics.Int) -> (Basics.Int -> model -> model) -> Field model

Modify an int field in the model. Takes a label, min/max bounds on the value, a getter, and a setter. Renders as a slider in the form.

floatSlider : String -> { min : Basics.Float, max : Basics.Float } -> (model -> Basics.Float) -> (Basics.Float -> model -> model) -> Field model

Modify an float field in the model. Takes a label, min/max bounds on the value, a getter, and a setter. Renders as a slider in the form.

textField : String -> (model -> String) -> (String -> model -> model) -> Field model

Modify an String field in the model). Takes a label, a getter, and a setter. Renders as a text field in the form.

colorPicker : String -> (model -> Color) -> (Color -> model -> model) -> Field model

Modify an Color field in the model (this type comes from avh4/elm-color). Takes a label, a getter, and a setter. Renders as a color picker in the form.

enumPicker : String -> List ( String, a ) -> (model -> a) -> (a -> model -> model) -> Field model

Pick from a list of values. Takes a label, a list of values and their labels (the labels are what you will see in the UI as well as what will be used in the URL), a getter and a setter.

Customizing the example

These are options you can apply to a configuration to add a few more bells and whistles to your examples:

withTitle : String -> Configuration model -> Configuration model

Add a title to your form. Will also set it as the HTML tag.</p> <p><a name="//apple_ref/cpp/Function/animatedWith" class="dashAnchor"></a></p> <div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div> <p><strong> <a class="mono" name="animatedWith" href="#animatedWith">animatedWith</a> <span class="grey"> :</span> </strong><span class="mono">(model <span class="grey">-></span> model <span class="grey">-></span> Basics.Float <span class="grey">-></span> model) <span class="grey">-></span> Basics.Int <span class="grey">-></span> Configuration model <span class="grey">-></span> Configuration model</span></p> <p>Animate transitions between different model states. To do this, you will need to supply an interpolation function, that takes a starting state, a target state and a parameter that goes betwen 0 and 1.</p> <p>Also, you should provide a duration in ms.</p> <p><a name="//apple_ref/cpp/Function/makeFormOnTop" class="dashAnchor"></a></p> <div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div> <p><strong> <a class="mono" name="makeFormOnTop" href="#makeFormOnTop">makeFormOnTop</a> <span class="grey"> :</span> </strong><span class="mono">Configuration model <span class="grey">-></span> Configuration model</span></p> <p>For normal configurations we normally render the form on the right of the view. This will change it to be rendered on top.</p> <p><a name="//apple_ref/cpp/Function/makeFormOnRight" class="dashAnchor"></a></p> <div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div> <p><strong> <a class="mono" name="makeFormOnRight" href="#makeFormOnRight">makeFormOnRight</a> <span class="grey"> :</span> </strong><span class="mono">Configuration model <span class="grey">-></span> Configuration model</span></p> <p>Tabbed configurations render the form on the top of the view. This will change it to be rendered on the right.</p> <p><a name="//apple_ref/cpp/Function/withCustomCss" class="dashAnchor"></a></p> <div style="padding: 0px; margin: 0px; height: 1px; background-color: rgb(216, 221, 225);"></div> <p><strong> <a class="mono" name="withCustomCss" href="#withCustomCss">withCustomCss</a> <span class="grey"> :</span> </strong><span class="mono">String <span class="grey">-></span> Configuration model <span class="grey">-></span> Configuration model</span></p> <p>Give this a block of CSS as a string and it will take care of adding it to the DOM with a proper tag.</p> <p>Useful for conveniently adding some flair without needing to mess with <code class="elm">Html</code>.</p> <p>Also note that the elements we add are style-able and have stable classes. Simply look through the generated DOM to find the appropriate class names.</p> </div"> </body> </html>