DIV type mismatch

Hi,
How can I fix this error?

The List.map accountRow accountslist will produce an array of DIV rows. e.g. [ div[] [], div [] [], …]
But I want to wrap them into a parent DIV.

The second argument to div has to be a list of HTML elements and your List.map call return sich a list. But then you surround it with square brackets, producing a list of lists (although the outer list contains only one element). So the solution is to replace the square brackets around the List.map call by parentheses.

2 Likes

I have tried that already, same error.
It seems like what should work is List.map accountRow accountslist |> div [] but I’m getting error on another place.

List.map accountRow accountslist |> div [], div [] <| List.map accountRow accountslist and div [] (List.map accountRow accountslist) are all equivalent and any of them should work for the error you show here.

The error that I am now getting is this
image

Yes, that’s a different error. Most likely you need to change the signature of contentFinal to Content msg

You cannot have a Html Msg inside a Html msg.

Also, for the fun of it, I have refactored your code:


viewAccountList accounts =
    div [ class "row" ]
        [ div [ class "col-md-4" ] [ text "Id" ]
        , div [ class "col-md-4" ] [ text "Code" ]
        , div [ class "col-md-4" ] [ text "Title" ]
        ]
        :: List.map accountRow accountsList
        |> div []


viewAccounts accounts =
    Maybe.map viewAccountList accounts
        |> Maybe.withDefault (p [] [ text "No records to show" ])
        |> contentFinal

The issue looks like is you “view function” signature instead “-> Html msg” needs to be “-> Html Msg” essentially the “msg” in lower case is a place holder type and the compiler detected that your code is using the “Msg”. You can check this thread that has better explanation. Html Msg vs Html msg?

Thanks for refactoring. Appreciate that, beginner like will learn from the feedback. I’m trying that out now.

Btw, I have this separate PageContent.elm file imported which I’d like to be the base content of all the sub pages.

`
module Page.PageContent exposing (…)

import Html exposing (…)

type alias Content msg =
{ title : String
, content : List (Html msg)
}
`

Example from my Homepage:
`module Page.Home exposing (…)

import Html exposing (…)
import Html.Attributes exposing (…)
import Page.PageContent as PC exposing (…)

homePage : PC.Content msg
homePage =
{ title = “Home”
, content = p [] [ text “Home Page” ]
}
`

All the Html created in Elm will end up in one of the browser functions.

If the Html has event handlers, then the function that includes that Html has to have a concrete type in its return (e.g. Html Msg not Html msg). All the functions that call this function have to have concrete type in their return.

So it seems like I need to get rid of my PageContent.elm and use Html Msg to all?

That helper is OK. It’s just a decorator and is fine to have msg.

You need to be careful when you use it. For example, the signature for homePage is fine the way it is right now BUT somePage that has event handlers should be somePage : PC.Content Msg

Yeah, that’s true. I like the idea of having this pretty small helper to handle the title and content. For a simple page like Home it’s not a problem. But when I started to use in a page with logic I got messed up. My project still small I guess.
It’s 6 KB in zip. I can send it to you if your willing to continue to assist. Thanks

If possible, put it in a github repository and I’ll take a look .

Here is the github repo https://github.com/mvperez/elm-spa.git
I will greatly appreciate if you can refactor things more I can study.
Thank you so much!

There were only two errors in the code:

First is a common one for people just starting out: you need to Html.map the view message type from the page type to the main type. Like this:

contentPage : Model -> Html Msg
contentPage model =
    let
        page =
            case model.page of
                HomePage ->
                    Home.homePage

                ListAccountsPage pageModel ->
                    let
                        content =
                            Accounts.view pageModel
                                |> Html.map ListAccountsOnGet
                    in
                    content

                AboutPage ->
                    About.aboutPage
    in
    page

Also, the ListAccountsOnGet should be ListAccountsMsg. The wrapper is for all messages in the Page.Msg

The second error was in the main view. It should be like this:

view : Model -> Browser.Document Msg
view model =
    let
        content =
            contentPage model

        log1 =
            log "Page Content => " content
    in
    { title = "Accounting"
    , body =
        [ ul []
            [ viewLink "/" "home"
            , viewLink "/about" "about"
            , viewLink "/accounts" "accounts"
            ]
        , content
        ]
    }

For some reason, instead of content you had content.content. If you actually expected that to work, it might be helpful to explain your reasoning for content.content as this might lead to more learning.
Some things are tricky in the beginning.

1 Like

Thanks @pdamoc! Appreciate much. The content.content is because I previously had PageContent helper that has {title: String, content: List (Html msg)} which I already remove. If I still have that, I’m just display the .content. I will apply your changes. Then after that I need to study my code again. :slight_smile:

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