Toggle password visibility

Hi,

I am new to Elm and am trying to add a button that toggles the visibility of the password fields (either as the standard password type or as text) but while I can do that hard-coding the boolean, I am getting an error when I add the update functionality.

Here are the parts of the code:


type alias Model =
    { form : Form
    , view : View
    }

type alias Form =
    { ...
    , showPassword: Bool
    }

type Msg
    = ...
    | TogglePasswordVisibility

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
    ...
        TogglePasswordVisibility -> 
            let
                updatePasswordVisibility = { model.form | showPassword = not model.form.showPassword} 
            in
            ({ model | form = updatePasswordVisibility}, Cmd.none )


div
                [ class "text-sm mx-auto my-4 px-4 py-1 bg-slate-100 hover:bg-slate-200 duration-300 text-slate-900 w-36 rounded-full cursor-pointer "]
                [ button
                    [ class "mr-2"
                    ]
                    [ ]    
                , text (if form.showPassword then "Hide password" else "Show password")
                ]

Happy for any help in trying to solve this.

You cannot update nested records with this syntax. Instead you should write:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
    ...
        TogglePasswordVisibility -> 
            let
                form = model.form
            in
            ({ model | form = { form | showPassword = not model.form.showPassword }}, Cmd.none)

Simplified working example here: https://ellie-app.com/pq7shtTvq2sa1

Thank you so much! I don’t really fully understand what is happening, but it is working.

Is it that you first set form to the current value and then toggle it? So form could be any variable?

1 Like

Yes, form could be anything. I could have used foo instead:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
    ...
        TogglePasswordVisibility -> 
            let
                foo = model.form
            in
            ({ model | form = { foo | showPassword = not model.form.showPassword }}, Cmd.none)

Since you cannot update nested records directly, you need to have an additional step. To go one step further, you could also do:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg ({ form } as model) =
    case msg of
    ...
        TogglePasswordVisibility -> 
            ({ model | form = { form | showPassword = not model.form.showPassword }}, Cmd.none)

Source: Elm FAQ

1 Like

Thank you so much for explaining it too me!

1 Like

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