formex v0.3.3 Formex.Type behaviour

In order to create a form, you need to create the Type file. It’s similar to Symfony’s way of creating forms.

Example:

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 category"
    ])
    |> add_button(:reset, "Reset form", phoenix_opts: [
      class: "btn-default"
    ])
    |> add_button(:submit, if(form.struct.id, do: "Edit", else: "Add"), phoenix_opts: [
      class: "btn-primary"
    ])
  end

  # optional
  def changeset_after_create_callback(changeset) do
    # do an extra validation
    changeset
  end
end

Nested forms

*_to_one

We have models User, and UserInfo. The UserInfo contains extra information that we don’t want, for some reason, store in the User model.

schema "users" do
  field :first_name, :string
  field :last_name, :string
  belongs_to :user_info, App.UserInfo
end
schema "user_infos" do
  field :section, :string
  field :organisation_cell, :string
  has_one :user, App.User
end

Note: belongs_to can also be placed in UserInfo and so on, it doesn’t matter in this example.

Our form will consist of two modules:

user_type.ex

defmodule App.UserType do
  use Formex.Type

  def build_form(form) do
    form
    |> add(:text_input, :first_name)
    |> add(:text_input, :last_name)
    |> add_form(App.UserInfoType, :user_info)
  end
end

user_info_type.ex

defmodule App.UserInfoType do
  use Formex.Type

  def build_form( form ) do
    form
    |> add(:text_input, :section)
    |> add(:text_input, :organisation_cell)
  end
end

Our form can be displayed in various ways:

  • Print whole form, with nested form, at once

    <%= formex_rows f %>
  • Standard

    <%= formex_row f, :first_name %>
    <%= formex_row f, :last_name %>
    <%= formex_row f, :user_info %>
  • Set a form template for nested form

    <%= formex_row f, :first_name %>
    <%= formex_row f, :last_name %>
    <div class="form-horizontal">
      <%= formex_row f, :user_info, template: Formex.Template.BootstrapHorizontal %>
    </div>

At the moment it is not possible to write more sophisticated template for subform.

*_to_many

Work in progress

Summary

Functions

Adds a button to the form

Embeds a form of assoc to the main form

Callbacks

In this callback you have to add fields to the form

Callback that will be called after changeset creation. In this function you can for example add an extra validation to your changeset

Functions

add(form, type_or_module, name, opts \\ [])
add(form :: Form.t, type_or_module :: Atom.t, name :: Atom.t, opts :: Map.t) :: Form.t

Adds a field to the form.

If the type_or_module is an atom, then this function invokes Formex.Field.create_field/4. Otherwise, the Formex.CustomField.create_field/3 is called.

add_button(form, type, label, opts \\ [])
add_button(form :: Form.t, type :: Atom.t, label :: String.t, opts :: Map.t) :: Form.t

Adds a button to the form.

The type may be either :submit or :reset. This function invokes Formex.Button.create_button/3.

add_form(form, type, name, opts \\ [])
add_form(form :: Form.t, type :: any, name :: Atom.t, opts :: Map.t) :: Form.t

Embeds a form of assoc to the main form.

If a struct of this form is not already preloaded, it will be loaded.

Options

Callbacks

build_form(form)
build_form(form :: Formex.Form.t) :: Formex.Form.t

In this callback you have to add fields to the form.

changeset_after_create_callback(changeset)
changeset_after_create_callback(changeset :: Ecto.Changeset.t) :: Ecto.Changeset.t

Callback that will be called after changeset creation. In this function you can for example add an extra validation to your changeset.