Peter Raeves
Peter Raeves

Reputation: 516

How to use Fields in Elm 0.13

I have been trying to get the fields to work, but keep failing. I have also been trying to look for examples, but the only examples I could find are using Elm 0.14, which use the new Channel API which isn't available in Elm 0.13.

So I started from the example offered in the catalog

import Graphics.Input.Field (..)
import Graphics.Input (..)

name : Input Content
name = input noContent

nameField : Signal Element
nameField = field defaultStyle name.handle identity "Name" <~ name.signal

And in order to use the field I tried

main : Signal Element
main = Signal.lift2 display Window.dimensions gameState

display : (Int,Int) -> GameState -> Element
display (w,h) g =
    container w h middle <|
        collage gameWidth gameHeight
            (if  | g.state == Menu ->
                    [ rect gameWidth gameHeight
                        |> filled black
                    , toForm nameField
                    , plainText "*The name entered in the nameField*"
                    ]
                | otherwise -> []
            )

But I keep getting the following error

Expected Type: Signal.Signal Graphics.Element.Element
Actual Type: Graphics.Element.Element

Why isn't the element a signal anymore... The function definition clearly states it should output a signal, right? Now how would I be able to enter a name, that I would then be able to use inside a variable?

Upvotes: 1

Views: 236

Answers (1)

Apanatshka
Apanatshka

Reputation: 5958

Elm 0.13 had some annoyingly confusing type error messages. Expected/Actual are usually swapped. In this case the problem comes from using nameField : Signal Element in display : (Int,Int) -> GameState -> Element. display is a pure (non-signal) function, but to be pure, you can't use a signal anywhere in there. To solve this, hoist the nameField signal up a level, to main. To use what is entered in the field, use the input signal:

main : Signal Element
main = Signal.lift4 display Window.dimensions gameState name.signal

nameField : Content -> Element
nameField = field defaultStyle name.handle identity "Name"

display : (Int,Int) -> GameState -> Content -> Element
display (w,h) g currentContent =
    container w h middle <|
        collage gameWidth gameHeight
            (if  | g.state == Menu ->
                    [ rect gameWidth gameHeight
                        |> filled black
                    , toForm (nameField currentContent) -- use something other than `currentContent` here to influence the field content. 
                    , plainText currentContent.string
                    ]
                | otherwise -> []
            )

Upvotes: 1

Related Questions