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" %>
</.form>
def password(assigns) do
~H"""
<div class="flex flex-col">
<%= label @f, @id %>
<%= password_input @f, @id, value: input_value(@f, @id) %>
<%= error_tag @f, @id %>
</div>
"""
end
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} />
<FormField
type="text"
opts={placeholder: "Enter your username"}
label="Username"
field={:username}
/>
<FormField
type="password"
opts={placeholder: "Enter your password"}
label="Password"
field={: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
.
2 Likes
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
<Form
for={@changeset}
action={Routes.user_registration_path(@socket, :create)}
trigger_action={@trigger_submit}
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} />
<FormField
type="password"
value={Ecto.Changeset.get_change(@changeset, :password)}
opts={placeholder: "Password"}
field={:password}
/>
<Button class="w-full mt-5 blue" phx_disable_with="Welcome...">
Register
</Button>
</Form>
@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.
<PasswordInput
:if={@type == "password"}
value={input_value(form, field)}
opts={generate_text_field_options(assigns)}
class={input_css(field_has_errors?(form, field)), @input_additional_class}
/>
I added the 3rd line now, and it started working.
Thanks.
1 Like