I am trying to extract params from a handle_event callback and i think this protocol is getting in the way. What could possibly be the problem?..the role_id is a string from a form submission. The code is so long…i dont think i can share it.
The error means you are trying to interpolate a tuple into a template. Tuples can’t be cast to string, or HTML.Safe
in this case but for all intents and purposes that’s the same thing.
So you have code somewhere that will look something like this:
<div some_attr={{:role_id, "is invalid"}}>
or maybe:
<%= {:role_id, "is invalid"} %>
Or possibly:
<%= @assign_that_contains_the_offending_tuple %>
I’ll get back …thanks for the response
here is the code for the input field role_id…i don’t see where it went wrong. Input.text_input is a Phoenix.HTML.FormField
Hi @cobra, it’s really hard to provide help with what you have put up there. We need to see actual error messages and the code they are coming from. You mentioned that you are trying to extract params from a handle_event
callback - what is the code for this callback, and what is actually failing?
Also, when you paste code, it is best to paste it as code in triple-backslash delimiters rather than a screenshot, so people can read it on a phone and also paste modifications to the code.
Generally, when I am debugging a handle_event
issue I find the easiest way is to print the params to the console, e.g.
def handle_event("event_name", params, socket) do
IO.inspect(params)
{:noreply, socket}
end
here is the handle_event callback …thanks for the response
\\
def handle_event(“submit”, %{“membership” => membership_params}, socket) do
send_update(MODULE, id: socket.assigns.form_name, update: :toggle_submit, value: true)
user_id =
Enum.find_value(socket.assigns.users, fn user ->
if user.name == Map.get(membership_params, "user_id"), do: user.id, else: nil
end)
membership_params = Map.merge(membership_params, %{"user_id" => user_id})
organization_id =
Enum.find_value(socket.assigns.organizations, fn org ->
if org.name == Map.get(membership_params, "organization_id"), do: org.id, else: nil
end)
membership_params = Map.merge(membership_params, %{"organization_id" => organization_id})
workspace_id =
Enum.find_value(socket.assigns.workspaces, fn workspace ->
if workspace.name == Map.get(membership_params, "workspace_id"),
do: workspace.id,
else: nil
end)
membership_params = Map.merge(membership_params, %{"workspace_id" => workspace_id})
dbg(membership_params)
form = socket.assigns.form |> AshPhoenix.Form.validate(membership_params)
AshPhoenix.Form.errors(form)
|> case do
[] ->
submit_form(socket, membership_params)
# insert_data(membership_params)
errors ->
send_update(__MODULE__,
id: socket.assigns.form_name,
update: :toggle_submit,
value: false
)
socket =
socket
|> assign(:form, form)
|> assign(:errors, errors)
{:noreply, socket}
end
end
\\
here is the error handling functions…
\\
defp field_touched(field, name) do
MapSet.member?(field.form.source.touched_forms, to_string(name))
end
defp get_field_errors(field, name) do
case field_touched(field, name) do
true →
{message, _} =
field.form.errors
|> Keyword.get(name, {“”, })
(to_string(name) |> String.capitalize()) <> " " <> message
_ ->
""
end
end
\\
and here is the code for the field role_id
\\
<Layout.col class="space-y-1.5">
<label for={@form[:role_id].name <> "_field"}>
<Text.text class="text-tremor-content">
Role
</Text.text>
</label>
<Input.text_input
id={@form[:role_id].name}
name={@form[:role_id].name}
placeholder="Enter value"
type="text"
field={@form[:role_id]}
value={@form[:role_id].value}
error={
@form[:role_id].errors != [] && field_touched(@form[:role_id], :name) == true
}
error_message={get_field_errors(@form[:role_id], :name)}
required="true"
/>
</Layout.col>
\\
Any Response will be highly Appreciated
i forgot the actual error and the params
\\
membership_params #=> %{
“level” => “organization”,
“organization_id” => “042c1e66-076f-497c-8266-161ba0532f5a”,
“role_id” => “ksksk54655”,
“user_id” => “1b8fe486-c8a5-42ba-89dc-f88195610f7a”,
“workspace_id” => “b8f8cc14-a1c8-4b78-8cb5-0ddd11d217b0”
}
[debug] HANDLE EVENT “submit” in SonganoteWeb.MembershipLive.Index
Component: SonganoteWeb.MembershipLive.FormComponent
Parameters: %{“membership” => %{“level” => “organization”, “organization_id” => “Dean Org”, “role_id” => “ksksk54655”, “user_id” => “Dean”, “workspace_id” => “nellyworkspace”}}
[debug] Replied in 8ms
[error] GenServer #PID<0.1087.0> terminating
** (Protocol.UndefinedError) protocol Phoenix.HTML.Safe not implemented for {:role_id, “is invalid”} of type Tuple. This protocol is implemented for the following type(s): Ash.CiString, Ash.NotLoaded, Atom, BitString, Date, DateTime, Decimal, Float, Integer, List, NaiveDateTime, Phoenix.HTML.Form, Phoenix.LiveComponent.CID, Phoenix.LiveView.Component, Phoenix.LiveView.Comprehension, Phoenix.LiveView.JS, Phoenix.LiveView.Rendered, Time, Tuple, URI
(phoenix_html 3.3.3) lib/phoenix_html/safe.ex:97: Phoenix.HTML.Safe.Tuple.to_iodata/1
(songanote_web 0.1.0) lib/songanote_web/membership/components/form.membership.ex:48: anonymous fn/3 in SonganoteWeb.MembershipLive.FormComponent.render/1
\\
Thank you
So it’s like @sodapopcan said - you are trying to render something that can’t automatically be rendered. I would guess it’s something to do with the return of get_field_errors(@form[:role_id], :name)
- maybe wrap it in an inspect
to confirm (i.e. inspect(get_field_errors(@form[:role_id], :name))
. If it’s not that, try wrapping other values in turn with inspect
in case something weird is going on with your form processing - e.g. @form[:role_id].value