Generating html from and embedded schema

Hello everyone!

I’m facing an issue and would love to hear your thoughts or opinions before diving deeper.

Problem
I need to generate a form dynamically based on embedded schemas. For example:

# my_custom_embedded_schema_1.ex
embedded_schema do
  field :value1, :string
  field :value2, :boolean
  field :value3, :integer
end

# my_custom_embedded_schema_2.ex
embedded_schema do
  field :other_value_1, :string
  field :other_value2, :boolean
  field :other_value3, :integer
end
...

Current Approach
In my LiveView, I’m pattern matching against each custom schema and manually generating the corresponding HEEx template:

# my_custos_forms.ex

def generate(my_custom_embedded_schema_1, assigns) do
  ~H"""
  <.simple_form
    for={@my_custom_embedded_schema_1_form}
    phx-submit="save"
    phx-target={@myself}
    id="my_custom_embedded_schema_1_form"
    phx-change="validate"
    phx-debounce="500"
  >
    <div class="grid grid-cols-3 gap-4">
      <.input field={@my_custom_embedded_schema_1_form[:value1]} label="value1" />
      <.input field={@my_custom_embedded_schema_1_form[:value2]} label="value2" />
      <.input field={@my_custom_embedded_schema_1_form[:value3]} label="value3" />
    </div>
  </.simple_form>
  """
end

def generate(my_custom_embedded_schema_2, assigns) do
  # Similar implementation for other schemas
end

Pain Point

Every time I add or modify a schema, I have to manually update the forms. This is tedious and prone to errors.

Idea

I’m considering building a form generator that can dynamically generate the appropriate HTML based on the fields in the embedded schema. The goal is to reduce the manual effort required to update forms whenever a schema changes.

Questions

  • Has anyone implemented something similar or encountered a similar use case?
  • Are there libraries, best practices, or patterns in the Elixir/Phoenix ecosystem that could help streamline this process?
  • Any potential pitfalls I should be aware of before investing time into building a generator like this?

I’d love to hear your insights!

Yes, this is possible by using the reflection API provided by ecto, namely what you are looking for is: MySchema.__schema__(:fields). This is however very raw and you need to careful about what kind of types you want to render, not to mention that it will not work for associations.

I think what more specifically you might be looking for is to_form/2, it should contain most of the features you require.

1 Like

I asked the same on the elixir discord server, this is a summary of what the answer was:

Attempting to derive forms from schemas is generally not worth the effort and often ends up being more complex than expected, both in implementation and usage. Over a project’s lifetime, schemas tend to change less than anticipated, and adding fields manually to forms is quick and straightforward.

Key considerations against this approach:

  • Handling multiple forms for the same schema.
  • Managing custom layouts (e.g., aligning fields on the same line).
  • Deciding where to define labels, hints, and descriptions—these are often better suited to the view or web layer rather than the core application.

Ultimately, such abstractions usually result in a less flexible, worse version of HTML. It’s better to keep the user interface (HTML forms) and the data model separate, avoiding derivation of one from the other.

Not sure how much it’s applicable to your problem but AshPhoenix has an auto feature which is really cool. Maybe look into it.
AshPhoenix.Form.Auto

This handles the “structure” and validations etc. but not individual fields, for the same reason that the previous poster described. You still define all the inputs yourself and that kind of thing. More info/example here: Nested Forms — ash_phoenix v2.1.14

2 Likes