Packages
formex
0.2.0
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Form library for Phoenix with Ecto support
Current section
Files
Jump to
Current section
Files
README.md
# Formex
Formex is an abstract layer that helps to build forms in Phoenix and Ecto. With this library you
don't write changeset, but a separate module that declares fields of form
(like in [Symfony](https://symfony.com/doc/current/forms.html#creating-form-classes)).
Formex will build changeset and additional Ecto queries (to get options for `<select>`) for itself.
Formex also comes with helper functions for templating. For now it only supports Bootstrap.
## Installation
`mix.exs`
```elixir
def deps do
[{:formex, "~> 0.2.0"}]
end
def application do
[applications: [:formex]]
end
```
`config/config.exs`
```elixir
config :formex,
repo: App.Repo,
translate_error: &App.ErrorHelpers.translate_error/1
```
`web/web.ex`
```elixir
def controller do
quote do
import Formex.Builder
end
end
def view do
quote do
import Formex.View
end
end
```
## Usage
We have models Article and Category:
```elixir
schema "articles" do
field :title, :string
field :content, :string
field :hidden, :boolean
belongs_to :category, App.Category
end
```
```elixir
schema "categories" do
field :name, :string
end
```
Let's create a form for Article using Formex:
```elixir
# /web/form/article_type.ex
defmodule App.ArticleType do
use Formex.Type
alias Formex.CustomField.SelectAssoc
def build_form(form) do
form
|> add(:text_input, :title, label: "Title")
|> add(:textarea, :content, label: "Content", phoenix_opts: [
rows: 4
])
|> add(:checkbox, :hidden, label: "Is hidden", required: false)
|> add(SelectAssoc, :category_id, label: "Category", phoenix_opts: [
prompt: "Choose a category"
])
end
end
```
We need to modify slightly a controller:
```elixir
def new(conn, _params) do
form = create_form(App.ArticleType, %Article{})
render(conn, "new.html", form: form)
end
def create(conn, %{"article" => article_params}) do
App.ArticleType
|> create_form(%Article{}, article_params)
|> insert_form_data
|> case do
{:ok, _article} ->
conn
|> put_flash(:info, "Article created successfully.")
|> redirect(to: article_path(conn, :index))
{:error, form} ->
render(conn, "new.html", form: form)
end
end
```
Template:
`form.html.eex`
```
<%= formex_form_for @form, @action, fn f -> %>
<%= if @form.changeset.action do %>...<% end %>
<%= formex_row f, :name %>
<%= formex_row f, :content %>
<%= formex_row f, :category_id %>
<%# or generate all fields at once: formex_rows f %>
...
<% end %>
```
Also replace `changeset: @changeset` with `form: @form` in `new.html.eex`
Optional CSS:
```css
.required .control-label:after {
content: '*';
margin-right: 3px;
}
```
final effect:
<img src="http://i.imgur.com/Hi1YE5b.png" width="502px">
It's very simple, isn't it?
You don't need to create any changeset nor write a query to get options for a Category select.
Furthermore, the form code is separated from the template.
## Documentation
[https://hexdocs.pm/formex](https://hexdocs.pm/formex)
### TODO
- [ ] more options for `Formex.CustomField.SelectAssoc`
- [x] `choice_name`
- [ ] `choice_query`
- [ ] `GROUP BY`
- [ ] validate if sent `<option>` exists in generated `:select`
- [ ] nested forms
- [ ] templating
- [ ] tests