Is me or is building form in phoenix very tedious? Especially form with table associations?

I have to refer to the pragprog phoenix >= 1.4 book every time I have to build CRUD for a table that have association with another table.

Formex library is great but it’s outdated and I couldn’t get it to work with 1.4. I felt if I work any more at it, it’ll become a hack which may make my life a living hell when I upgrade in future.

The problem I think and what Formex library tried to solve is that to have a drop down menu of an associated table in the form you have to write code in the context, model, controller, view, and template files. This doesn’t seem very orthogonal nor modular.

Anyway if this is really want it suppose to be like then okay. I’m just curious if there are any other solution out there and hopefully this doesn’t come across as a rant.

Thanks.

An example is what I’m currently doing in my side project:

Here’s the model snippet:

company.ex

  26   def changeset(company, attrs) do
  27     company
  ...
  32     |> assoc_constraint(:company_main_activity)
  33   end

company_main_activity.ex

  20   def alphabetical(query) do
  21     from c in query, order_by: c.main_activity
  22   end

Here’s the context file:

  33   def list_alphabetical_company_main_activities do
  34     Company_Main_Activity
  35     |> Company_Main_Activity.alphabetical()
  36     |> Repo.all()
  37   end

Then you got the controller:

  9   plug :load_company_main_activities when action in [:new, :create, :edit, :update]
...
  75   defp load_company_main_activities(conn, _) do
  76     assign(conn, :company_main_activities, Context.list_alphabetical_company_main_activities())
  77   end

Then the view:

  12   def company_main_activity_select_options(company_main_activities) do
  13     for company_main_activity <- company_main_activities, do: {company_main_activity.main_activity, company_main_activity.id}
  14   end

And then the template (ignore since that’s straight forward).

The one solution I got the make it a bit more modular is that I move the plug from controller into it’s own file and save it into a plugs folder in appname_web (idea taken from Alchemist Camp.

1 Like

It’s not just you, I found it very cumbersome as well. It feels too much magic and too deviated from writing actual HTML forms. I wish Phoenix had gone the same route of something like Laravel - provide some basic helpers such as csrf(), route() etc so that we could write forms in plain html and not some Elixir macros, and move Phoenix Form to its own optional package. I’ve liked everything about Elixir/Phoenix so far except for how we have to learn new syntax to write a form.

2 Likes

It‘s already separate from phoenix core: phoenix_html. Also you can build forms already manually if you want to. There are csrf helpers that you can use. It‘s just that forms usually involve a lot of logic about selecting a value to display out of defaults/values set for the data/values supplied from prev. submissions and also error handling, which are imho quite well handled by the FormData protocol of phoenix_html. But nothing will stop you from not using that an build forms using raw html and eex.

9 Likes

You can use only view method to do all things beside modifying changeset if you are expecting the query to be uniq for a view.

1 Like

It’s not too hard to write functions to remove most of the tediousness. I have a ‘Surface’ module that does the great majority of the various work for me, from tables to elements to more. :slight_smile:

They tend to be rather project specific, so don’t hesitate to write such helpers. :slight_smile:

3 Likes