How to select a value from a drop down list in a form and save it in database?

Hi,

I’ve generated a resource:
mix phx.gen.html Cpm Bmr bmrs user_id:references:users age:integer weight:integer height:integer sex:string

I would like to create a form in which a user can choose his sex using a select list with ‘Male’ and ‘Female’ options. How can I achive this? For now thats what I have.

defmodule Calorie.Cpm.Bmr do
  use Ecto.Schema
  import Ecto.Changeset

 schema "bmrs" do
    field :age, :integer
    field :height, :integer
    field :weight, :integer
    field :sex, :string
    belongs_to :user, Calorie.Accounts.User

    timestamps()
 end

def changeset(bmr, attrs) do
    bmr
    |> cast(attrs, [:weight, :age, :height, :sex])
    |> validate_required([:weight, :age, :height, :sex])
  end
end

defmodule Calorie.Repo.Migrations.CreateBmrs do
  use Ecto.Migration

  def change do
    create table(:bmrs) do
      add :weight, :integer
      add :age, :integer
      add :height, :integer
      add :sex, :string
      add :user_id, references(:users, on_delete: :nothing)

      timestamps()
    end

    create index(:bmrs, [:user_id])
  end
end

<%= 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, :weight %>
  <%= number_input f, :weight %>
  <%= error_tag f, :weight %>

  <%= label f, :age %>
  <%= number_input f, :age %>
  <%= error_tag f, :age %>

  <%= label f, :height %>
  <%= number_input f, :height %>
  <%= error_tag f, :height %>

  <%= label f, :sex %>
  <%= select f, :sex, prompt: "Choose sex" %>
  <%= error_tag f, :sex%>

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

defmodule CalorieWeb.BmrController do
  use CalorieWeb, :controller

  alias Calorie.Cpm
  alias Calorie.Cpm.Bmr

  def new(conn, _params, _current_user) do
    changeset = Cpm.change_bmr(%Bmr{})
    render(conn, "new.html", changeset: changeset)
  end

  def create(conn, %{"bmr" => bmr_params}, current_user) do
    case Cpm.create_bmr(current_user, bmr_params) do
      {:ok, bmr} ->
        conn
        |> put_flash(:info, "Bmr created successfully.")
        |> redirect(to: Routes.bmr_path(conn, :show, bmr))

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

I am not sure if I added correct and needed code. I will be grateful for help.

The select helper expects you to provide an Enumerable containing the possible selections a user can make. In your case, it could be:

<%= select f, :sex, ["Male", "Female"], prompt: "Choose sex" %>

or if the database expects different values:

<%= select f, :sex, ["Male": "M", "Female": "F"], prompt: "Choose sex" %>
<%= select f, :sex, ["Male": 1, "Female": 2], prompt: "Choose sex" %>
...etc

For reference, see Phoenix.HTML.Form - select/4

4 Likes

Thank you very much for your time! It did resolve my issue and help me understand it!

1 Like