Long form: how to handle model, Msg and update?

133 views
Skip to first unread message

Eduardo Cuducos

unread,
Sep 12, 2016, 12:08:25 PM9/12/16
to Elm Discuss
Hi all,

I'm writing an application that has a “advanced search” form. In my context it means a form with approx. 20 input fields.

As a newbie the only way I could think of coding this is quite repetitive. I bet that there is a more cleaver and a DRY way to do it, but I couldn't figure out how. Any ideias?

This is the terrible idea I have in mind:

1. My initial model would have 20 form fields definition like that:

initialModel = 
    { form :
        { applicant =
            { label = "Applicant name"
            , selected = True
            , value = ""
            , msg = UpdateApplicant
            }
        , year =
            { label = "Year"
            , selected = True
            , value = ""
            , msg = UpdateYear
            }
        , state =
            { label = "State"
            , selected = True
            , value = ""
            , msg = UpdateState
            }
        …
        }
    …
    }    


2. Consequently my type Msg would have another 20 very similar fields:

type Msg
    = UpdateApplicant String
    | UpdateYear String
    | UpdateState
    | …

3. And my update would have 20 very similar cases:

update msg model =
    case msg of
        UpdateApplicant query ->
            let
                applicant =
                    model.form.applicant

                newApplicant =
                    { applicant | value = query }

                currentForm =
                    model.form

                form =
                    { currentForm | applicant = newApplicant }
            in
                ( { model | form = form }, Cmd.none )

        UpdateYear query ->
            let
                year =
                    model.form.year

                newYear =
                    { year | value = query }

                currentForm =
                    model.form

                form =
                    { currentForm | year = newYear }
            in
                ( { model | form = form }, Cmd.none )

        UpdateState query ->
            let
                state =
                    model.form.state

                newState =
                    { state | value = query }

                currentForm =
                    model.form

                form =
                    { currentForm | state = newState }
            in
                ( { model | form = form }, Cmd.none )

Many thanks,

Ambrose Laing

unread,
Sep 12, 2016, 3:15:12 PM9/12/16
to Elm Discuss
Something like this can be made to work, if you don't care about relaxing the type safety which is provided by your current approach:


initialModel =
   
{ form : Dict.fromList
       
[ ("applicant",

           
{ label = "Applicant name"
           
, selected = True
           
, value = ""

           
})
       
, ("year",

           
{ label = "Year"
           
, selected = True
           
, value = ""

           
})
       
, ("state",

           
{ label = "State"
           
, selected = True
           
, value = ""

           
})
       

       
]
   

   
}


type
Msg
   
= Update String String



update msg model
=
   
case
msg of
       
Update fieldName query ->
            let
                entry
=
                   
Dict.get fieldName model.form

                newEntry
=
                   
{ entry | value = query }

                form
= Dict.insert fieldName newEntry model.form
           
in

               
( { model | form = form }, Cmd.none )


You should make it safer by including run-time checks that the first string argument (fieldName) is one of your 20 possibilities, before doing the above replacement, and if it isn't then you should specify what to do (maybe ignore it).

Eduardo Cuducos

unread,
Sep 12, 2016, 3:17:02 PM9/12/16
to Elm Discuss
Many thanks, Ambrose! That was very helpful indeed ; ) Gonna make it work.

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ambrose Kofi Laing

unread,
Sep 12, 2016, 3:19:06 PM9/12/16
to elm-d...@googlegroups.com
There is a bug in my code which is that Dict.get returns a Maybe, so you will have to handle the possibility that the fieldName is not found using maybe 

case entry of
    Just something -> ...
    Nothing -> ...


To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/vrCjxS58XeY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss+unsubscribe@googlegroups.com.

Eduardo Cuducos

unread,
Sep 12, 2016, 6:53:54 PM9/12/16
to elm-d...@googlegroups.com
No worries, Ambrose.
I haven't read you snippets literally, but they were quite expressive in the sense of showing me how Dict could work in my case.
Already treated the Maybe cases and it's working beautifully.
Once more, thank you very much ; )

To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/vrCjxS58XeY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages