I’m working on a CRUD application setup as an umbrella app made up of an Elixir and Phoenix apps. I’m at the point of creating a web form to allow for adding new data. I’m stuck on the error:
protocol Phoenix.HTML.FormData not implemented for #Ecto.Changeset<action: nil, changes: %{},
errors: [name: {"can't be blank", [validation: :required]}, description: {"can't be blank", [validation: :required]}],
data: #Agency.Role<>, valid?: false> of type Ecto.Changeset (a struct).
This protocol is implemented for the following type(s): Plug.Conn, Atom
- What does the error message mean in general?
- How do I fix it?
I had a similar error and after getting no where, I scrapped the app a started again. It was related to another protocol but the message worded the same. I think I’m missing some foundation and will therefore appreciate detailed answers if possible.
Below are the sections of my code that I think is relevant to my problems:
The url to the page is:
http://localhost:4000/roles/new
Router
scope "/", AgencyWeb do
pipe_through :browser
get "/", PageController, :index
resources "/rates", RateController, only: [:index]
resources "/roles", RoleController, only: [:index, :show, :create, :new]
end
RoleController
defmodule AgencyWeb.RoleController do
use AgencyWeb, :controller
def index(conn, _params) do
roles = Agency.list_roles()
render(conn, "index.html", roles: roles)
end
def new(conn, _params) do
role = Agency.new_role()
render(conn, "new.html", role: role)
end
def show(conn, _params) do
role = Agency.new_role()
render(conn, "show.html", role: role)
end
def create(conn, %{"role" => role_params}) do
{:ok, role} = Agency.insert_role(role_params)
redirect(conn, to: Routes.role_path(conn, :show, role))
end
end
Role
defmodule Agency.Role do
use Ecto.Schema
import Ecto.Changeset
schema "roles" do
field(:name, :string)
field(:description, :string)
timestamps()
end
def changeset(role, params \\ %{}) do
role
|> cast(params, [:name, :description])
|> validate_required([:name, :description])
|> validate_length(:name, min: 3)
|> validate_length(:description, min: 3, max: 200)
end
end
Agency
defmodule Agency do
@moduledoc """
Main Agency app module providing access to database functions
"""
alias Agency.{Repo, Rate, Role}
@repo Repo
# Role API
def list_roles do
@repo.all(Role)
end
def get_role(id) do
@repo.get!(Role, id)
end
def insert_role(attrs) do
%Role{}
|> Role.changeset(attrs)
|> @repo.insert()
end
def update_role(%Agency.Role{} = role, updates) do
role
|> Role.changeset(updates)
|> @repo.update()
end
def new_role, do: Role.changeset(%Role{})
end
New Role Template
<h1>New Role</h1>
<%= form_for @role, Routes.role_path(@conn, :create), fn f -> %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= label f, :description %>
<%= text_input f, :description %>
<div>
<%= submit "Submit" %>
</div>
<% end %>
Thanks