Trouble Associating Children to a Parent and Updating the Relationship

I have Events, which can have many Contacts. On the Event edit/new form I have a multiple select box where a user can choose Contacts which should be associated with the event.

I have setup associations in the schema and database migrations. I got the form working as well with the group select. When you select a bunch of groups and then click new or edit, it succeeds fine. However the event_id in the Contacts table doesn’t change and when I go back to edit Event there are no groups selected.

In my child changesets I have been using assoc_constraint but I understand that is only for the receiving end of the belongs_to relationship. What is the most idiomatic way to update my Contacts table to be correctly associated with the Event?

Event Schema

defmodule App.Event do
  use Ecto.Schema
  import Ecto.Changeset

  schema "events" do
    field :name, :string
    field :description, :string

    has_many :contacts, App.Contact

    timestamps()
  end

  @doc false
  def changeset(event, attrs) do
    required_fields = [:name]
    optional_fields = [:description]

    event
    |> cast(attrs, required_fields ++ optional_fields)
    |> validate_required(required_fields)
  end
end

Contact Schema

defmodule App.Contact do
  use Ecto.Schema
  import Ecto.Changeset

  schema "contacts" do
    field :email, :string
    field :name, :string
    field :phonenumber, :string

    belongs_to :event, App.Event

    timestamps()
  end

  @doc false
  def changeset(contact, attrs) do
    required_fields = [:name, :phonenumber]
    optional_fields = [:email]

    contact
    |> cast(attrs, required_fields ++ optional_fields)
    |> validate_required(required_fields)
  end
end

Event Migration

defmodule App.Repo.Migrations.CreateEvents do
  use Ecto.Migration

  def change do
    create table(:events) do
      add :name, :string, null: false
      add :description, :text
 
      timestamps()
    end

    create unique_index(:events, [:name])
  end
end

Contact Migration

defmodule App.Repo.Migrations.CreateContacts do
  use Ecto.Migration

  def change do
    create table(:contacts) do
      add :name, :string, null: false
      add :email, :string
      add :phonenumber, :string, null: false
      add :event_id, references(:events, on_delete: :delete_all)

      timestamps()
    end

  end
end

I think the most idiomatic way would be to use cast_assoc in Event.changeset.