Password field how to retain value in Surface

When we want to retain the value of a password field across events, we use

value: input_value(f, :password)

for the password field in the LiveView. Otherwise, after validation, the field becomes empty. How should we specify the same in a surface form?

1 Like

It works the same way in Surface. Can you provide the Surface code snippet that isn’t behaving properly?

         <.form let={f} for={@changeset} action={Routes.user_registration_path(@socket, :create)} phx-change="validate" phx_trigger_action={@trigger_submit} phx-submit="save">
            <.text f={f}, id={:username} />
            <.email f={f}, id={:email} />
            <.password f={f}, id={:password} />
            <%= submit "Save" %>
  def password(assigns) do
        <div class="flex flex-col">
            <%= label @f, @id %>
            <%= password_input @f, @id, value: input_value(@f, @id) %>
            <%= error_tag @f, @id %>

That is how would I write in plain LiveView using heex components. Now, in surface

<Form for={@changeset} opts={phx_submit: "save", phx_change: "validate"}>
              <FormField type="text" opts={placeholder: "Enter your email"} label="Email" field={:email} />
                opts={placeholder: "Enter your username"}
                opts={placeholder: "Enter your password"}        

Here there is no f variable to identify the form - so can we use the changeset to extract the field value?

What is <FormField>? That doesn’t ship with Surface.

If you use <PasswordInput> that ships with Surface under the hood, you should be able to set value from the changeset:

value={get_change(@changeset, :password)}

Using Ecto.Changeset.get_change.

1 Like

Got it.
Yes - is a component I have written with styling.
Did not occur to me to use get_change.

Thanks, the problem is resolved.

1 Like
                action={Routes.user_registration_path(@socket, :create)}
                opts={phx_submit: "save", phx_change: "validate"}
                <FormField type="email" opts={placeholder: "Enter your email"} field={:email} />
                <FormField type="text" opts={placeholder: "Username"} field={:username} />
                  value={Ecto.Changeset.get_change(@changeset, :password)}
                  opts={placeholder: "Password"}
                <Button class="w-full mt-5 blue" phx_disable_with="Welcome...">

@paulstatezny This is the code. The password field is getting empty on submit. So, it is raising validation error. Any idea what I am missing?

It sounds like it’s now behaving properly on change, but emptying the field on submit. Is that correct?

Does your “submit” function emit a @changeset with the password field set? Or does it set something like hashed_password and leave password empty?

1 Like

Thanks. You gave the right pointer. The issue is in the FormField component.

          :if={@type == "password"}
          value={input_value(form, field)}
          class={input_css(field_has_errors?(form, field)), @input_additional_class}

I added the 3rd line now, and it started working.

1 Like