Form Validations does not appear

Hello there,

I have a simple :create action in my controller and everytime I try submitting the form with invalid data it redirects to the :index route without showing any error_tag
here is my code:
controller


  def new(conn, _params) do
    changeset = Accounts.change_student(%Student{})
    render(conn, "new.html", changeset: changeset)
  end

  def create(conn, %{"student" => student_params}) do
    case Accounts.create_student(student_params) do
      {:ok, student} ->
        conn
        |> put_flash(:info, "Welcome aboard, You Should Recieve A Confirmation Mail Soon!")
        |> redirect(to: Routes.student_path(conn, :show, student))

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

Changeset:

def changeset(student, attrs) do
    student
    |> cast(attrs, [:username, :password, :firstName, :lastName, :birthdate, :gender, :email, :uniID])
    |> validate_required([:username, :password, :firstName, :lastName, :birthdate, :gender, :email, :uniID])
    |> unique_constraint(:username)
    |> unique_constraint(:email)
  end

Form Templae:

<%= form_for @changeset, @action, fn f -> %>
  <%= if @changeset.action do %>
    <div class="alert alert-danger">
      <p>Oops, something went wrong! Please check the errors below.</p>
    </div>
  <% end %>

  <%= label f, :username %>
  <%= text_input f, :username %>
  <%= error_tag f, :username %>

  <%= label f, :password %>
  <%= password_input f, :password %>
  <%= error_tag f, :password %>

  <%= label f, :firstName %>
  <%= text_input f, :firstName %>
  <%= error_tag f, :firstName %>

  <%= label f, :lastName %>
  <%= text_input f, :lastName %>
  <%= error_tag f, :lastName %>

  <%= label f, :birthdate %>
  <%= date_select f, :birthdate %>
  <%= error_tag f, :birthdate %>

  <%= label f, :gender %>
  <%= select f, :gender, ["Male", "Female", "Other", "Rather Not Specify"] %>
  <%= error_tag f, :gender %>

  <%= label f, :email %>
  <%= text_input f, :email %>
  <%= error_tag f, :email %>

  <%= label f, :uniID %>
  <%= text_input f, :uniID %>
  <%= error_tag f, :uniID %>

  <div>
    <%= submit "Submit" %>
  </div>
<% end %>

UPDATE: I noticed that it also does not insert when the data is valid so it a problem with the DB I think, can you help me with that?

Thanks in advance!

Your original issue sounds like the changeset isn’t getting an action set on it; can you post your Accounts.create_student function?

1 Like

yes, sure. Here you go

def create_student(attrs \\ %{}) do
    %Student{}
    |> Student.changeset(attrs)
    |> Repo.insert()
  end

Can you show us the schema and DB migration as well? One thing that caught my eye was the unusual naming: firstName. Is this aligned with the DB definition?

Can you try creating the student from IEx session?

iex> Accounts.create_student(%{...})

yes sure,
Schema:

schema "students" do
    field :birthdate, :date
    field :email, :string
    field :firstName, :string
    field :gender, :string
    field :lastName, :string
    field :password, :string
    field :uniID, :string
    field :username, :string

    timestamps()
  end

Migration:

 def change do
    create table(:students) do
      add :username, :string
      add :password, :string
      add :firstName, :string
      add :lastName, :string
      add :birthdate, :date
      add :gender, :string
      add :email, :string
      add :uniID, :string

      timestamps()
    end

    create unique_index(:students, [:username])
    create unique_index(:students, [:email])
  end

iex session output:

iex(3)> Accounts.create_student()
{:error,
 #Ecto.Changeset<
   action: :insert,
   changes: %{},
   errors: [
     username: {"can't be blank", [validation: :required]},
     password: {"can't be blank", [validation: :required]},
     firstName: {"can't be blank", [validation: :required]},
     lastName: {"can't be blank", [validation: :required]},
     birthdate: {"can't be blank", [validation: :required]},
     gender: {"can't be blank", [validation: :required]},
     email: {"can't be blank", [validation: :required]},
     uniID: {"can't be blank", [validation: :required]}
   ],
   data: #Lean.Accounts.Student<>,
   valid?: false
 >}
iex(5)> Accounts.create_student(%{username: "aligredo", password: "12345678", firstName: "Ali", lastName: "Ahmed", birthdate: Date.utc_today, gender: "Male", email: 
"a@g.com", uniID: "uni"})
[debug] QUERY OK db=141.0ms queue=15.0ms idle=1344.0ms
INSERT INTO "students" ("birthdate","email","firstName","gender","lastName","password","uniID","username","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) RETURNING "id" [~D[2020-06-02], "a@g.com", "Ali", "Male", "Ahmed", "$pbkdf2-sha512$160000$1eq4lltlYOc2ugq4PZ01mA$52kswsGGYFM/DtM1yB4RyxeE.N6zBypO2cS311cVLuTgRZTY6hXvdJaIOzQmBZRsx1LADyUihCgQcx.ktTI8yw", "uni", "aligredo", ~N[2020-06-02 11:40:20], ~N[2020-06-02 11:40:20]]
{:ok,
 %Lean.Accounts.Student{
   __meta__: #Ecto.Schema.Metadata<:loaded, "students">,
   birthdate: ~D[2020-06-02],
   email: "a@g.com",
   firstName: "Ali",
   gender: "Male",
   id: 1,
   inserted_at: ~N[2020-06-02 11:40:20],
   lastName: "Ahmed",
   password: "$pbkdf2-sha512$160000$1eq4lltlYOc2ugq4PZ01mA$52kswsGGYFM/DtM1yB4RyxeE.N6zBypO2cS311cVLuTgRZTY6hXvdJaIOzQmBZRsx1LADyUihCgQcx.ktTI8yw",
   uniID: "uni",
   updated_at: ~N[2020-06-02 11:40:20],
   username: "aligredo"
 }}

I’m no expert in Phoenix, but shouldn’t this point to a correct route instead of @action? What’s the value of the @action assign?

The phoenix generators create new.html.eex and edit.html.eex, which both render form.html.eex setting @action to an appropriate value.

1 Like

exactly, here is it

<%= render "form.html", Map.put(assigns, :action, Routes.student_path(@conn, :create)) %>

Makes sense, but I’m out of ideas then. I’m not sure you’re posting the complete code, since there seems to be some missing parts (like password hashing). Do you happen to have any plugs (auth?) that would redirect the user?

1 Like

Not yet I’m just setting up the accounts context, I think the problem is with my router.ex not with validations
check this New Topic I added my router code there.

Thank you so much!