dwyl / adoro

❤️ The little publishing tool you'll love using. [work-in-progress]
http://www.dwyl.io/
32 stars 8 forks source link

Auto generating a form from an Ecto schema #108

Closed Danwhy closed 5 years ago

Danwhy commented 5 years ago

To access a schema's fields, we can use the schema/1 function provided by Ecto.Schema. We then need to filter out those that we don't want to create ourselves (the id and timestamps).

defmodule ExampleWeb.UserController do
  use ExampleWeb, :controller

  alias Example.User

  def new(conn, _params) do
    fields = 
      :fields
      |> User.__schema__() 
      |> Enum.reject(&(&1 in [:id, :inserted_at, :updated_at]))

    render(conn, "new.html", fields: fields)
  end
end

We can use the Phoenix.HTML.Form.input_type function to determine which type of html form input should be used for each field. We can pass a third argument to input_type if we want to define the mapping ourselves. See https://hexdocs.pm/phoenix_html/Phoenix.HTML.Form.html#input_type/3

Then we use apply/3 to call the Phoenix.HTML.Form input function that maps to our type with the given arguments.

defmodule ExampleWeb.UserView do
  use ExampleWeb, :view

  def input(form, field, opts) do
    type = Phoenix.HTML.Form.input_type(form, field)
    apply(Phoenix.HTML.Form, type, [form, field, opts])
  end
end

Then in our html, we just iterate through the fields, passing each one to our input/3 function.

<%= form_for @changeset, @action, fn f -> %>
  <%= for field <- @fields do %>
    <div class="form-group">
      <%= label f, field, class: "control-label" %>
      <%= input f, field, class: "form-control" %>
      <%= error_tag f, field %>
    </div>
  <% end %>

  <div class="form-group">
    <%= submit "Submit", class: "btn btn-primary" %>
  </div>
<% end %>
iteles commented 5 years ago

@nelsonic @Danwhy Do you feel we're now already doing this with https://github.com/dwyl/autoform ?

nelsonic commented 5 years ago

@iteles this issue was opened before Autoform was created. image

Closing.