5

I have a text like this

Special menu:\nFrenchfire 1ea\nHamborger 2ea\nMeatball 1ea

and i want to breakline it in Elm with Html tag such as pre or span and it should show like this

Special menu:
Frenchfire 1ea
Hamborger 2ea
Meatball 1ea

i have no idea to concat br[][] in string if it is an Elm but if javascript i can replace string like replace(/\n/g,'<br/>') and it done.

Earn Asdsa
  • 172
  • 2
  • 9
  • what is current output? – Ravi Aug 20 '19 at 06:52
  • i write a code like ``` div [] (List.map (\s -> span [] [ text s , br [] [] ] ) (String.replace "\n" text) ) ``` but i have error This `replace` call produces: #String -> String# But `map` needs the 2nd argument to be: #List String# – Earn Asdsa Aug 20 '19 at 07:06
  • 4
    `String.replace` takes input of type String and returns a String. `List.map` requires an input as List of Strings i.e. List String as the error states. Instead of replace, maybe you could use `String.split`? That'll remove the newline chars and return a List of Strings. EDIT: `String.lines` already breaks the String on newline char and returns a List of String, better to use that. – kaskelotti Aug 20 '19 at 07:31
  • 2
    @kaskelotti You should make that a proper answer. – glennsl Aug 20 '19 at 11:22

2 Answers2

16

You mentioned a <pre> tag, so let's try that first:

import Html exposing (pre, text)

pre []
    [ text "Special menu:\nFrenchfire 1ea\nHamborger 2ea\nMeatball 1ea" ]

Renders as:

Special menu:
Frenchfire 1ea
Hamborger 2ea
Meatball 1ea

Or you could split the string into individual lines. String.split accomplishes this:

String.split "\n" "Special menu:\nFrenchfire 1ea\nHamborger 2ea\nMeatball 1ea"

Even better, as kaskelotti aptly suggested:

String.lines "Special menu:\nFrenchfire 1ea\nHamborger 2ea\nMeatball 1ea"

Use List.map to transform the Strings into Html and List.intersperse to insert <br /> tags between them:

import Html exposing (br, text)
List.intersperse (br [] [])
        (List.map text
            (String.lines "Special menu:\nFrenchfire 1ea\nHamborger 2ea\nMeatball 1ea")
        )

You end up with a list of Html elements. Done!

See it rendered here.

Or, if you prefer, use an itemized list:

import Html exposing (Html, div, h3, li, text, ul)


listItem : String -> Html msg
listItem content =
    li [] [ text content ]


main : Html msg
main =
    let
        split =
            String.lines "Special menu:\nFrenchfire 1ea\nHamborger 2ea\nMeatball 1ea"

        headline =
            Maybe.withDefault "Items:" (List.head split)

        items =
            Maybe.withDefault [] (List.tail split)
    in
    div []
        [ h3 [] [ text headline ]
        , ul [] (List.map listItem items)
        ]

See it rendered here.

O.O.Balance
  • 2,930
  • 5
  • 23
  • 35
2

String.replace takes input of type String and returns a String. List.map requires an input as List of Strings i.e. List String as the error states.

You can solve this by using String.split or String.lines. Both will take a String as input and return a List of String, which is what List.map requires.

The difference is that String.lines is a built-in function meant for splitting the String with newline chars (\n) and String.split is a general purpose utility for splitting a String by any delimiter.

For this particular case, I'd go with String.lines, since the name documents its purpose already. Presence of String.split is good to know for future cases.

kaskelotti
  • 4,709
  • 9
  • 45
  • 72