[018.3] elm-mdl: Textfields and Menus


A super brief introduction to text fields and menus in elm-mdl. With a bonus really long pair programming session where we refactor some code with Luke Westby and introduce elm-mdl into a project.

Subscribe now

In the last episode, we introduced elm-mdl. We used a layout and a button. We'll look at Textfields and Menus today. We're going to look at them in the context of a project I've been working on, called colluder

Project

I paired with Luke Westby to clean up the code for colluder a bit, and after that was done we styled it up a bit with elm-mdl. Normally this would just be a 5 minute text episode, but instead there's a 90 minute bonus pairing video showing our pairing session :)

Anyway, if you have an Html button and an Html numeric textfield, like so:

div [ id Styles.TopControls ]
    [ button [ onClick TogglePaused ] [ text pauseText ]
    , input
        [ onInput (SetBPM << Result.withDefault 128 << String.toInt)
        , placeholder "BPM"
        , type' "number"
        , value (toString model.bpm)

You can replace them both with Material components thusly:

import Material.Button as Button
import Material.Textfield as Textfield

div []
    [ Button.render Mdl
        [ 0 ]
        model.mdl
        [ Button.onClick TogglePaused ]
        [ text pauseText ]
    , Textfield.render Mdl
        [ 1 ]
        model.mdl
        [ Textfield.onInput (SetBPM << Result.withDefault 128 << String.toInt)
        , Textfield.floatingLabel
        , Textfield.label "BPM"
        , Textfield.value (toString model.bpm)
        ]

If you have a dropdown, you're basically out of luck. There's no Material Design select element, exactly. We tried to replace it with a Menu but for my use case neither the original dropdown nor the menu really make sense. At any rate, if you want to approximate a select with a menu in elm-mdl, you could do something like this:

Menu.render Mdl [0] model.mdl
  [ Menu.ripple, Menu.bottomLeft ]
  [ Menu.item
      [ Menu.onSelect (Consume "Milk") ]
      [ text "Milk" ]
  , Menu.item
      [ Menu.onSelect (Consume "Oranges") ]
      [ text "Oranges" ]
  ]

Ultimately, though, dropdowns aren't exactly a thing in Material Design Lite yet. This isn't as bad as you might think - I've linked to an enlightening video in the resources section on this very topic.

If you're using Menus, you really also need to add the Material Menu sub to your subscriptions:

subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.batch
        ([ audioContextSub
         , oggEnabledSub
         , fontsLoadedSub
         , playedNoteSub
         , playSequenceStartedSub
         , Menu.subs Mdl model.mdl -- <-- Here's where we added it.
         ]
            ++ (tickSub model)
        )

Otherwise, when you click outside the menus they'll just stick around and taunt you. Also, we learned that you really probably shouldn't make a 128 entry menu in elm-mdl for performance reasons, but also don't do that to users :)

Summary

So I'm not sure if today's episode is amazing or a letdown. As a text episode, it's kind of lame - there's just a couple of basic introductions to using Material Design Lite components. But as far as the accompanying pair programming bonus video goes, I kind of think it's amazing. We'll see. The moral of the story is: elm-mdl is still really freaking cool and easy to work with.

Resources

Published on 08.11.2016