Protocol Phoenix.HTML.Safe not implemented for {:role_id, "is invalid"} of type Tuple

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 %>
1 Like

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
1 Like

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 :smile: :smile:

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 :blush: :upside_down_face:

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

1 Like