Desperate to get this parent lookup working in simple form .input type=select

I have a phoenix app with a lot of related tables. In particular, I have a regions (think territory) as a parent table that has a related child table consisting of 3-digit zip codes that are in a table region_zips.
I need a select form element in the region_zip form (created by phx.gen.html) in order to make sure I’m picking the correct region for a particular 3 digit zip code. I cannot get this to work no matter how many ways I’ve tried. I know the lookup in def new(conn, _params) works. It’s just not working in the form. I would greatly appreciate any assistance. Thanks in advance. Bill

def new(conn, _params) do
    regions = Regions.lookup_regions() #  Valid results are [%{id: 1, name: "Test" },...]
    changeset = RegionZips.change_region_zip(%RegionZip{})
    render(conn, :new, changeset: changeset, regions: regions)
  end

The related form is

<.simple_form :let={f} for={@changeset} action={@action}>
  <.error :if={@changeset.action}>
    Oops, something went wrong! Please check the errors below.
  </.error>
  <.input field={f[:region_id]} type="select" options={@regions} label="Region" />
  <.input field={f[:zip_prefix]} type="text" label="Zip prefix" />
  <:actions>
    <.button>Save Region zip</.button>
  </:actions>
</.simple_form>

I have to make some assumptions about the error you are seeing, but I believe I ran into a similar problem for a gardening app. If you are encountering an error like

[error] GenServer #PID<0.739.0> terminating
** (Protocol.UndefinedError) protocol Enumerable not implemented for type Regions.Region (a struct). This protocol is implemented for the following type(s): ...

then the problem is that the input function with type="select" needs the structure of options changed a bit. The generated code uses Phoenix.HTML.Form.options_for_select. Since you are passing the region id as the value for the field and the region name as the label, I would use

def new(conn, _params) do
  regions = Enum.map(Regions.lookup_regions(), fn region -> {region.name, region.id} end) #  Valid results are now [{"Test", 1}, ...]
  changeset = RegionZips.change_region_zip(%RegionZip{})
  render(conn, :new, changeset: changeset, regions: regions)
end

to display the Region names and pass the id in the form input. The simple_form should not need to be changed. I hope this helps.

Appreciate the reply but that wasn’t it. I’ve formatted the regions lookup in a number of ways as an array of maps, tuples, keywords, i, etc. I still get key error message that lookup of regions passed as an arg to the render function executes.

KeyError at GET /region_zips/new
key :regions not found in: %{
  action: "/region_zips",
  __given__: %{
    action: "/region_zips",
    __changed__: nil,
    changeset: #Ecto.Changeset<
      action: nil,
      changes: %{},
      errors: [
        region_id: {"can't be blank", [validation: :required]},
        zip_prefix: {"can't be blank", [validation: :required]}
      ],
      data: #Crm.RegionZips.RegionZip<>,
      valid?: false,
      ...
    >
  }, 

Take a look at the implementation of category_opts/1 in this guide. It’s the same as what you’re trying to do.

edit: also, the reason why @regions isn’t found in the form assigns is because it has to be passed in when the form is rendered in new.html.heex. Your @regions assign exists for the new action not the form, which is a function component. There should be a line like this where you’ll have to add regions as an attr for the form.

<.thing_form regions={@regions} changeset={@changeset} action={~p"/things"} />

Thanks. I’ll check it out and reply back when I get a chance to work on it.

I’ve been traveling & haven’t had time to dig into this but I believe you hit the nail on the head of what my problem was. I absolutely love Elixir but sometimes I get lost how things get passed along. In the related region_zips VIEW field, I will pass regions as an attribute which I failed to do. I see where I was previously passing in as an action. I’ve already corrected for the proper formatting of the options in terms of key and value pairs. Thanks for the assist it is greatly appreciated.