Exercise in the documentation (maybe) (C<>F)

There is an exercise suggested on
https://guide.elm-lang.org/error_handling/maybe.html
https://ellie-app.com/3P9hcDhdsc5a1

I have gone through the documentation up till this point now.
But don’t see how i can solve this. Any pointers, hints?

I my opinion:

  • the model needs to be changed if multiple input boxes are there: so an extra string value should be kept

I do not fully get how the html alike code in the viewconverter works

PS: it is missing module Main exposing (…)

Hi,

Welcome to Elm.

Yes, it is. So if you add module Main exposing (..) (two dots not three) to the top line, it will compile. I haven’t used Ellie myself, so don’t know its history - this error may be a throwback from when Ellie didn’t require it - Maybe. Just a thought.

Yes, if you want to extend the example to add more conversions, then you will need to change the model accordingly. Rather than just calling the input box input, you could name them all to be something more specific.

What exactly don’t you understand? It takes data from either of the Maybe branches and displays it in the Dom. If you could be more specific it would be helpful.

HTH

This is the adapted code, the original code is on https://ellie-app.com/3P9hcDhdsc5a1

i struggle with the view and view converter

module Main exposing (..)

import Browser
import Html exposing (Html, Attribute, span, input, text)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)



-- MAIN


main =
  Browser.sandbox { init = init, update = update, view = view }



-- MODEL


type alias Model =
  { inputCelsius : String,
    inputFahrenheit : String
  }


init : Model
init =
  { inputCelsius = "10",
    inputFahrenheit = "5"}



-- UPDATE


type Msg
  = ChangeCelsius String |
    ChangeFahrenheit String  


update : Msg -> Model -> Model
update msg model =
  case msg of
    ChangeCelsius newInputCelsius ->
      { model | inputCelsius = newInputCelsius }
    ChangeFahrenheit newInputFahrenheit ->
      { model | inputFahrenheit = newInputFahrenheit }


-- VIEW
-- concrete formulas not important

view : Model -> Html Msg
view model =
  case String.toFloat model.inputCelsius of
    Just celsius ->
      viewConverter model.inputCelsius "blue" (String.fromFloat (celsius * 1.8 + 32))
--    viewConverter model.inputFahrenheit "green" (String.fromFloat (fahrenheit/2))
    Nothing ->
      viewConverter model.inputCelsius "red" "???"
-- adding a second case is not an option?, how can one continue?  
--  case String.toFloat model.inputFahrenheit of
--    Just celsius ->
--      viewConverter model.inputFahrenheit "green" (String.fromFloat (fahrenheit/2))
--    Nothing ->
--      viewConverter model.inputFahrenheit "red" "???"



viewConverter : String -> String -> String -> Html Msg
viewConverter userInput color equivalentTemp =
  span []
    [ input [ value userInput, onInput ChangeCelsius, style "width" "40px" ] []
    , text "°C = "
    , span [ style "color" color ] [ text equivalentTemp ]
    , text "°F"    
    , input [ value userInput, onInput ChangeFahrenheit, style "width" "40px" ] []
    , text "°F = "
    , span [ style "color" color ] [ text equivalentTemp ]
    , text "°C"
    ]

You won’t be able to use viewConverter the same way as in the original example. The parameters passed in are being used for both inputs etc, so changing the value in one, will also change the value in the other. I guess you have already seen this happening.

If you break this down into two separate functions, it should start to become easier to solve.

celsiusViewConverter : String -> String -> String -> Html Msg
celsiusViewConverter userInput color equivalentTemp =
  span []
    [ input [ value userInput, onInput ChangeCelsius, style "width" "40px" ] []
    , text "°C = "
    , span [ style "color" color ] [ text equivalentTemp ]
    , text "°F"    
    ]

farenheitViewConverter : String -> String -> String -> Html Msg
farenheitViewConverter userInput color equivalentTemp =
  span []
    [input [ value userInput, onInput ChangeFahrenheit, style "width" "40px" ] []
    , text "°F = "
    , span [ style "color" color ] [ text equivalentTemp ]
    , text "°C"
    ]

Then you can use those functions in your view:

view : Model -> Html Msg
view model =
  let
    celsiusView =
      case String.toFloat model.inputCelsius of
        Just celsius ->
          celsiusViewConverter model.inputCelsius "blue" (String.fromFloat (celsius * 1.8 + 32))
        Nothing ->
          celsiusViewConverter model.inputCelsius "red" "???"

    farenheitView =
      case String.toFloat model.inputFarenheit of
        Just farenheit ->
          farenheitViewConverter model.inputFarenheit "blue" (String.fromFloat (fahrenheit/2))
        Nothing ->
          farenheitViewConverter model.inputFarenheit "red" "???"
  in
  span []
    [  celsiusView, farenheitView ]

There’s more than one way to skin a cat, but hopefully, this shows you the simplest approach.

Thank you for the feedback, the let … in was new for me.

The exercise also asked to have an appropiate bordercolor (trying it out)
I found the needed variable on “borderColor” on
https://package.elm-lang.org/packages/rtfeldman/elm-css/latest/Css

view model =
  let
    celsiusView =
      case String.toFloat model.inputCelsius of
        Just celsius ->
          celsiusViewConverter model.inputCelsius "blue" (String.fromFloat (celsius * 1.8 + 32))
        Nothing ->
          celsiusViewConverter model.inputCelsius "red" "???"

    fahrenheitView =
      case String.toFloat model.inputFahrenheit of
        Just fahrenheit ->
          fahrenheitViewConverter model.inputFahrenheit "blue" (String.fromFloat (fahrenheit / 2))
        Nothing ->
          fahrenheitViewConverter model.inputFahrenheit "red" "???"
  in
  span []
    [  celsiusView, fahrenheitView ]

celsiusViewConverter : String -> String -> String -> Html Msg
celsiusViewConverter userInput color equivalentTemp =
  span []
    [ input [ value userInput, onInput ChangeCelsius, style "width" "40px", style "borderColor" color ] []
    , text "°C = "
    , span [ style "color" color ] [ text equivalentTemp ]
    , text "°F"    
    ]

fahrenheitViewConverter : String -> String -> String -> Html Msg
fahrenheitViewConverter userInput color equivalentTemp =
  span []
    [input [ value userInput, onInput ChangeFahrenheit, style "width" "40px" , style "color" color, style "borderColor" "yellow" ] []
    , text "°F = "
    , span [ style "color" color ] [ text equivalentTemp ]
    , text "°C"
    ]
1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.