Code Monkey home page Code Monkey logo

formex's People

Contributors

jakub-zawislak avatar minibikini avatar simonprev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

formex's Issues

SelectAssoc inside embeds

Is there any way we can use selectassoc field type inside embeds

Like select element for posts inside embeds?

Example or documentation for embedded_schema

This is just a question rather than issue.

Is there any documentation where I can find how to use embedded_many or embedded_one with formex.

Thank you for this module! It's awesome! :D

formex_id and formex_delete fields are saved to database for embedded schemas

My embedded schemas look like this:

embedded_schema do
field :city
field :position
field :start_date, :date
field :end_date, :date

formex_collection_child() # <- this is added

end

After saving formex form with nested form and with form collections presented by embedded schemas I got such struct from the database:

%Hello.Hr.Data{
  experiences: [
    %Hello.Hr.Experience{
      city: "Kiev",
      end_date: ~D[2016-10-10],
      formex_delete: nil,
      formex_id: nil,
      id: "1191a0ce-73f5-4a44-868a-e58f4a71ff2c",
      position: "Chef",
      start_date: ~D[2014-04-15]
    },
    %Hello.Hr.Experience{
      city: "Lviv",
      end_date: ~D[2019-02-01],
      formex_delete: nil,
      formex_id: nil,
      id: "c230e653-8d15-4dd0-a12d-8498d6f92a3f",
      position: "Master",
      start_date: ~D[2016-11-01]
    }
  ],
  formex_delete: nil,
  formex_id: nil,
  id: "a50c6e8e-be35-4028-99f6-4744dbd439f6",
  welder: %Hello.Hr.Welder{
    formex_delete: nil,
    formex_id: nil,
    horizontal: true,
    id: "07a3a136-a6f2-4910-94f4-eca5507183da",
    vertical: false
  }
}

You see all embedded structs polluted by formex_id and formex_delete key value pairs.

Is there a way to do an array with checkboxes?

I have an array column with roles {:array, :string} => ["admin", "developer", "sponsor"]

I would like to have a checkbox for each one and if checked, they update the array with the content. Is that possible with Formex?

Module not found: Error: Can't resolve 'formex'

My installation is fresh new Phoenix 1.4, so there is a webpack.js project builder.

I added a dependency to the /assets/package.json file and it looks like this:

  "dependencies": {
    "phoenix": "file:../deps/phoenix",
    "phoenix_html": "file:../deps/phoenix_html",
    "formex": "file:../deps/formex"
  }

And added a line into /assets/js/app.js according to the documentation:

import {Collection} from 'formex'

But got the error:

ERROR in ./js/app.js
Module not found: Error: Can't resolve 'formex' in 'd:\test\hello\assets\js'

SelectAssoc not working for many_to_many

I am testing the many_to_many SelectAssoc for product to options many to many schema.

It is showing this error :

key :name not found in: %App.Option{meta: #Ecto.Schema.Metadata<:loaded, "options">, description: "opt1", factory: #Ecto.Association.NotLoaded, factory_id: 1, id: 6, inserted_at: #<DateTime(2017-04-18T02:00:39Z Etc/UTC)>, products: #Ecto.Association.NotLoaded, updated_at: #<DateTime(2017-04-18T02:00:39Z Etc/UTC)>}

It boils down to select_assoc.ex line 208 where row.name cannot be fetched from assoc.

Hidden Input

Is there a way to make an input hidden?

I'm looking to set a boolean in a nested form. I'm using custom_value to conditionally set it, but I'd like it hidden as well. I can do it with CSS but I thought there should be some better way.

Date and DateTime form field values don't correspond the types

My schema is:

defmodule Hello.Hr.Resume do
  use Ecto.Schema
  import Ecto.Changeset
  alias Hello.Hr.{Resume, Data, Welder, Experience}


  schema "resumes" do
    embeds_one :data, Data, on_replace: :update

    field :birthday, :date
    field :full_name, :string
    field :joined_at, :naive_datetime
    field :next_event, :utc_datetime
    field :start_work_time, :time

    timestamps()
  end

  @doc false
  def changeset(resume, attrs) do
    resume
    |> cast(attrs, [:full_name, :birthday, :joined_at, :next_event, :start_work_time])
    |> validate_required([:full_name, :birthday, :joined_at, :next_event, :start_work_time])
    |> cast_embed(:data)
  end

The type is:

defmodule Hello.Hr.ResumeType do
  use Formex.Type
  use Formex.Ecto.Type
  use Formex.Ecto.ChangesetValidator
  alias Hello.Hr.{Data, DataType}

  def build_form(form) do
    form
    |> add(:full_name, :text_input, [:required])
    |> add(:birthday, :date_select)
    |> add(:joined_at, :datetime_select)
    |> add(:next_event, :datetime_select)
    |> add(:start_work_time, :time_select)
    |> add(:data, DataType, struct_module: Data)
    |> add(:save, :submit)
  end
end

In my controller I have a create function:

  def create(conn, %{"resume" => resume_params}) do
    ResumeType
    |> create_form(%Resume{}, resume_params)
    |> handle_form
    |> case do
      {:ok, resume} ->
        resume = Hello.Repo.insert!(resume)
        redirect(conn, to: Routes.resume_path(conn, :show, resume))
      {:error, form} ->
        render(conn, "new.html", form: form)
    end
  end

and in the form template:

<%= formex_form_for @form, @action, fn f -> %>
  <%= if @form.submitted? do %>
    <div class="alert alert-danger">
      <p>Oops, something went wrong! Please check the errors below.</p>
    </div>
  <% end %>
  <%= formex_row f, :full_name %>
  <%= formex_row f, :birthday %>
  <%= formex_row f, :joined_at %>
  <%= formex_row f, :next_event %>
  <%= formex_row f, :start_work_time %>
  <%= formex_nested f, :data, fn fd -> %>
    <%= formex_nested fd, :welder, fn fw -> %>
      <%= formex_row fw, :vertical %>
      <%= formex_row fw, :horizontal %>
    <% end %>
    <%= formex_collection fd, :experiences %>
  <% end %>
  <%= formex_row f, :save %>
<% end %>

When I try to insert new resume I get:

** (exit) an exception was raised:
    ** (Ecto.ChangeError) value `%{"day" => "2", "month" => "3", "year" => "2014"}` for `Hello.Hr.Resume.birthday` in `insert` does not
match type :date

Formex + Money

Hi. I love your library! It makes form building incredibly fun and easy.

One a project of mine, I'm using the Money library for some of my columns. For example:

schema "campaigns" do
    field :name, :string
    field :bid_amount_cents, Money.Ecto.Type
  end

When I set up the type, it looks like this:

defmodule  MyWeb.CampaignType do
  use Formex.Type

  def build_form(form) do
    form
    |> add(:name, :text_input, label: "Name", validation: [presence: true])
    |> add(:bid_amount_cents, :number_input, label: "Bid Amount", validation: [presence: true])
    |> add(:save, :submit, label: "Submit", phoenix_opts: [
      class: "btn-primary"
    ])
  end
end

My issue is that the form field that it renders does not use the amount value of the bid_amount_cents. Right now when it gets the value, it uses @campaign.bid_amount_cents when I need it to use @campaign.bid_amount_cents.amount.

Is there a way to specify the value in the CampaignType above where I can derive the value as a function call? I assume this is possible with a custom field, but the docs are pretty shaky around custom fields and I can't find any good examples anywhere.

Thanks for your help!

Mapping modal <-> form that isn't 1:1

Can the modal and form use different field names / different structure?

defmodule App.Article do
  defstruct [:name, :properties] # name vs title, :properties is a map with :content key
end
defmodule App.ArticleType do
  use Formex.Type

  def build_form(form) do
    form
    |> add(:title, :text_input)
    |> add(:content, :textarea)
  end
end

Cannot use distillery for release due to function capture

My config looks like this:

config :formex,
  repo: App.Repo,
  validator: Formex.Ecto.ChangesetValidator,
  translate_error: &AppWeb.ErrorHelpers.translate_error/1

The translate error function capture is not compatible with distillery, so I can't build a release. bitwalker/distillery#185

If I don't use translate_error config option, I get BadFunctionError: expected a function, got: nil in lib/formex/validator.ex:96

Any possible solution?

ecto changeset from schema

Is there a way to access change set that have been defined with the schema rather than defining the in the validator section of the form type. This will just greatly simplify the process of code organisation. This just means that we will have access to the change set from other parts of the project.

I am still reviewing the formex_ecto

Module attribute for @repo evaluates to nil

Hey there!

I've run into this issue a couple times now, where @repo Application.get_env(:formex, :repo) evaluates to nil, which causes issues like ** (UndefinedFunctionError) function nil.preload/2 is undefined or private. So far I've been able to get things back on track by running mix deps.compile --force, but it doesn't seem like that's something that should have to be done occasionally.

I'll keep my eyes open to see if I can't find out how I'm causing this to happen.

csrf token was not found error on create action

My controller looks like this:

defmodule HelloWeb.ResumeFormexController do
  use HelloWeb, :controller
  alias Hello.Hr.{Resume, ResumeType}

  def index(conn, _params) do
    resumes = Hr.list_resumes()
    render(conn, "index.html", resumes: resumes)
  end

  def new(conn, params) do
    form = create_form(ResumeType, %Resume{})

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

  def create(conn, params) do
    ResumeType
    |> create_form(%Resume{}, params)
    |> handle_form
    |> case do
      {:ok, resume} ->
        redirect(conn, to: Routes.resume_path(conn, :show, resume))
      {:error, form} ->
        render(conn, "new.html", form: form)
    end
  end

  def show(conn, %{"id" => id}) do
    resume = Hr.get_resume!(id)
    inspect(resume)
    render(conn, "show.html", resume: resume)
  end
end

When I submit form I get:

iex(2)> [info] POST /resumes-formex
iex(2)> [debug] Processing with HelloWeb.ResumeFormexController.create/2
  Parameters: %{"_csrf_token" => "OgN4fAQFGwBJMG5xOxQpS38aIyFSJgAAmk7M0HNOqtA2Pdaz7Nvp3A==", "_utf8" => "тЬУ", "resume" => %{"birthday"
=> %{"day" => "2", "month" => "3", "year" => "2014"}, "data" => %{"experiences" => %{"0" => %{"city" => "Kiev", "end_date" => %{"day" => "20", "month" => "12", "year" => "2016"}, "formex_id" => "652e666a-6d9e-450c-bf5d-ee9f0d6e6b66", "position" => "Chef welder", "start_date" => %{"day" => "1", "month" => "8", "year" => "2014"}}, "1" => %{"city" => "Lvov", "end_date" => %{"day" => "1", "month" => "1", "year" => "2019"}, "formex_id" => "e89497aa-2f65-4aa5-b42e-4417569aeed7", "position" => "Master", "start_date" => %{"day" => "20", "month" => "12", "year" => "2016"}}}, "id" => "", "welder" => %{"horizontal" => "true", "id" => "", "vertical" => "false"}}, "full_name" => "John Doe", "joined_at" => %{"day" => "4", "hour" => "3", "minute" => "10", "month" => "6", "year" => "2016"}, "next_event" => %{"day" => "6", "hour" => "11", "minute" => "0", "month" => "10", "year" => "2019"}, "start_work_time" => %{"hour" => "7", "minute" => "30"}}}
  Pipelines: [:browser]
iex(2)> [info] Sent 500 in 47ms
iex(2)> [error] #PID<0.1056.0> running HelloWeb.Endpoint (connection #PID<0.1055.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: POST /resumes-formex
** (exit) an exception was raised:
    ** (KeyError) key :_csrf_token not found in: %Hello.Hr.Resume{__meta__: #Ecto.Schema.Metadata<:built, "resumes">, birthday: nil, data: nil, full_name: nil, id: nil, inserted_at: nil, joined_at: nil, next_event: nil, start_work_time: nil, updated_at: nil}
        (stdlib) :maps.get(:_csrf_token, %Hello.Hr.Resume{__meta__: #Ecto.Schema.Metadata<:built, "resumes">, birthday: nil, data: nil,
full_name: nil, id: nil, inserted_at: nil, joined_at: nil, next_event: nil, start_work_time: nil, updated_at: nil})
        (elixir) lib/map.ex:267: Map.update!/3
        (stdlib) maps.erl:257: :maps.fold_1/3
        (formex) lib/formex/builder.ex:146: Formex.Builder.apply_params/1
        (formex) lib/formex/builder.ex:52: Formex.Builder.create_form/5
        (hello) lib/hello_web/controllers/resume_formex_controller.ex:18: HelloWeb.ResumeFormexController.create/2
        (hello) lib/hello_web/controllers/resume_formex_controller.ex:1: HelloWeb.ResumeFormexController.action/2
        (hello) lib/hello_web/controllers/resume_formex_controller.ex:1: HelloWeb.ResumeFormexController.phoenix_controller_pipeline/2
        (hello) lib/hello_web/endpoint.ex:1: HelloWeb.Endpoint.instrument/4
        (phoenix) lib/phoenix/router.ex:275: Phoenix.Router.__call__/1
        (hello) lib/hello_web/endpoint.ex:1: HelloWeb.Endpoint.plug_builder_call/2
        (hello) lib/plug/debugger.ex:122: HelloWeb.Endpoint."call (overridable 3)"/2
        (hello) lib/hello_web/endpoint.ex:1: HelloWeb.Endpoint.call/2
        (phoenix) lib/phoenix/endpoint/cowboy2_handler.ex:34: Phoenix.Endpoint.Cowboy2Handler.init/2
        (cowboy) d:/test/hello/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
        (cowboy) d:/test/hello/deps/cowboy/src/cowboy_stream_h.erl:296: :cowboy_stream_h.execute/3
        (cowboy) d:/test/hello/deps/cowboy/src/cowboy_stream_h.erl:274: :cowboy_stream_h.request_process/3
        (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

Add button doesn't work

I have a 2 level deep nested form of resume with nested data field presented by embedded schema and inside of data there are embeds_one (nested form in formex's terms) welder schema and embeds_many experiences schemas (collection form in formex's terms).

The Add button for adding a collection of experiences is present in the form but doesn't work.

My installation:
Fresh new phoenix 1.4
mix.exs:

  def application do
    [
      mod: {Hello.Application, []},
      extra_applications: [:logger, :runtime_tools, :formex]
    ]
  end

  defp deps do
    [
      {:phoenix, "~> 1.4.0"},
      {:phoenix_pubsub, "~> 1.1"},
      {:phoenix_ecto, "~> 4.0"},
      {:ecto_sql, "~> 3.0"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 2.11"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:gettext, "~> 0.11"},
      {:jason, "~> 1.0"},
      {:plug_cowboy, "~> 2.0"},
      {:pow, "~> 1.0.1"},
      {:formex, "~> 0.6.0"},
      {:formex_ecto, "~> 0.2.0"}
    ]
  end

Schemas:

defmodule Hello.Hr.Resume do
  use Ecto.Schema
  import Ecto.Changeset
  alias Hello.Hr.{Resume, Data, Welder, Experience}


  schema "resumes" do
    embeds_one :data, Data, on_replace: :update

    field :birthday, :date
    field :full_name, :string
    field :joined_at, :naive_datetime
    field :next_event, :utc_datetime
    field :start_work_time, :time

    timestamps()
  end

  @doc false
  def changeset(resume, attrs) do
    resume
    |> cast(attrs, [:full_name, :birthday, :joined_at, :next_event, :start_work_time])
    |> validate_required([:full_name, :birthday, :joined_at, :next_event, :start_work_time])
    |> cast_embed(:data)
  end
defmodule Hello.Hr.Data do
  use Ecto.Schema
  use Formex.Ecto.Schema
  import Ecto.Changeset
  alias Hello.Hr.{Welder, Experience}

  embedded_schema do
    embeds_one :welder, Welder, on_replace: :update
    embeds_many :experiences, Experience, on_replace: :delete

    formex_collection_child()
  end

  @doc false
  def changeset(data, attrs) do
    data
    |> cast(attrs, [])
    |> cast_embed(:welder, required: true)
    |> cast_embed(:experiences, required: true)
  end
end
defmodule Hello.Hr.Welder do
  use Ecto.Schema
  import Ecto.Changeset
  use Formex.Ecto.Schema

  embedded_schema do
    field :vertical, :boolean, default: false
    field :horizontal, :boolean, default: false

    formex_collection_child()
  end

  def changeset(welder, attrs) do
    welder
    |> cast(attrs, [:vertical, :horizontal])
  end
end
defmodule Hello.Hr.Experience do
  use Ecto.Schema
  import Ecto.Changeset
  use Formex.Ecto.Schema
  
  embedded_schema do
    field :city
    field :position
    field :start_date, :date
    field :end_date, :date

    formex_collection_child()
  end

  def changeset(experience, attrs) do
    experience
    |> cast(attrs, [:city, :position, :start_date, :end_date])
    |> validate_required([:city, :position, :start_date, :end_date])
  end
end

Types:

defmodule Hello.Hr.ResumeType do
  use Formex.Type
  use Formex.Ecto.Type
  use Formex.Ecto.ChangesetValidator
  alias Hello.Hr.{Data, DataType}

  def build_form(form) do
    form
    |> add(:full_name, :text_input, [:required])
    |> add(:birthday, :date_select)
    |> add(:joined_at, :datetime_select)
    |> add(:next_event, :datetime_select)
    |> add(:start_work_time, :time_select)
    |> add(:data, DataType, struct_module: Data)
    |> add(:save, :submit)
  end
end
defmodule Hello.Hr.DataType do
  use Formex.Type
  use Formex.Ecto.Type
  use Formex.Ecto.ChangesetValidator
  alias Hello.Hr.{Welder, WelderType, Experience, ExperienceType}

  def build_form(form) do
    form
    |> add(:welder, WelderType, struct_module: Welder)
    |> add(:experiences, ExperienceType, struct_module: Experience)
  end
end
defmodule Hello.Hr.Welder do
  use Ecto.Schema
  import Ecto.Changeset
  use Formex.Ecto.Schema

  embedded_schema do
    field :vertical, :boolean, default: false
    field :horizontal, :boolean, default: false

    formex_collection_child()
  end

  def changeset(welder, attrs) do
    welder
    |> cast(attrs, [:vertical, :horizontal])
  end
end
defmodule Hello.Hr.ExperienceType do
  use Formex.Type
  use Formex.Ecto.Type
  use Formex.Ecto.ChangesetValidator

  def build_form(form) do
    form
    |> add(:city, :text_input)
    |> add(:position, :text_input)
    |> add(:start_date, :date_select)
    |> add(:end_date, :date_select)
  end
end

Controller:

defmodule HelloWeb.ResumeFormexController do
  use HelloWeb, :controller
  alias Hello.Hr.{Resume, ResumeType}

  def new(conn, params) do
    form = create_form(ResumeType, %Resume{})

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

Templates:
new.html.eex:

<h1>New Resume</h1>

<%= render "form.html", Map.put(assigns, :action, Routes.resume_formex_path(@conn, :create)) %>

<span><%= link "Back", to: Routes.resume_formex_path(@conn, :index) %></span>

form.html.eex:

<%= formex_form_for @form, @action, fn f -> %>
  <%= if @form.submitted? do %>
    <div class="alert alert-danger">
      <p>Oops, something went wrong! Please check the errors below.</p>
    </div>
  <% end %>
  <%= formex_row f, :full_name %>
  <%= formex_row f, :birthday %>
  <%= formex_row f, :joined_at %>
  <%= formex_row f, :next_event %>
  <%= formex_row f, :start_work_time %>
  <%= formex_nested f, :data, fn fd -> %>
    <%= formex_nested fd, :welder, fn fw -> %>
      <%= formex_row fw, :vertical %>
      <%= formex_row fw, :horizontal %>
    <% end %>
    <%= formex_collection fd, :experiences %>
  <% end %>
  <%= formex_row f, :save %>
<% end %>

Javascript
package.json:


  "dependencies": {
    "phoenix": "file:../deps/phoenix",
    "phoenix_html": "file:../deps/phoenix_html",
    "formex": "file:../deps/formex"
  },

app.js:
import {Collection} from '../../deps/formex'

The html of the form generated by formex looks like this (cut select's options for brevity):

<form accept-charset="UTF-8" action="/resumes-formex" method="post"><input name="_csrf_token" type="hidden" value="FAMhQQ0IAj9LJWUvGBl4YQIMfmcZEAAACknp9EWpsaJlsi0PJX+6xw=="><input name="_utf8" type="hidden" value="?">    <div class="form-group required"><label class="control-label col-sm-2" for="resume_full_name">full_name</label><div class="col-sm-10"><input class="form-control " id="resume_full_name" name="resume[full_name]" type="text"></div></div>
<div class="form-group required"><label class="control-label col-sm-2" for="resume_birthday">birthday</label><div class="col-sm-10"><select id="resume_birthday_year" name="resume[birthday][year]">...</select></div></div>
<div class="form-group required"><label class="control-label col-sm-2" for="resume_next_event">next_event</label><div class="col-sm-10"><select id="resume_next_event_year" name="resume[next_event][year]">...</select></div></div>
    
<div class="form-group required"><label class="control-label col-sm-2" for="resume_data_welder_vertical">vertical</label><div class="col-sm-10"><div class="checkbox"><label><input name="resume[data][welder][vertical]" type="hidden" value="false"><input class="" id="resume_data_welder_vertical" name="resume[data][welder][vertical]" type="checkbox" value="true"></label></div></div></div>      <div class="form-group required"><label class="control-label col-sm-2" for="resume_data_welder_horizontal">horizontal</label><div class="col-sm-10"><div class="checkbox"><label><input name="resume[data][welder][horizontal]" type="hidden" value="false"><input class="" id="resume_data_welder_horizontal" name="resume[data][welder][horizontal]" type="checkbox" value="true"></label></div></div></div>
<input id="resume_data_welder_id" name="resume[data][welder][id]" type="hidden" value="">    <div class="formex-collection" data-formex-prototype="&lt;div class=&quot;formex-collection-items&quot;&gt;&lt;div class=&quot;formex-collection-item formex-collection-item-new&quot; data-formex-index=&quot;0&quot; style=&quot;&quot;&gt;&lt;a class=&quot;formex-collection-item-remove&quot; data-formex-confirm=&quot;Are you sure?&quot; href=&quot;#&quot;&gt;&amp;times;&lt;/a&gt;&lt;div class=&quot;form-group required&quot;&gt;&lt;label class=&quot;control-label col-sm-2&quot; for=&quot;resume[data]_experiences___idx0___city&quot;&gt;city&lt;/label&gt;&lt;div class=&quot;col-sm-10&quot;&gt;&lt;input class=&quot;form-control &quot; id=&quot;resume[data]_experiences___idx0___city&quot; name=&quot;resume[data][experiences][__idx0__][city]&quot; type=&quot;text&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;form-group required&quot;&gt;&lt;label class=&quot;control-label col-sm-2&quot; for=&quot;resume[data]_experiences___idx0___position&quot;&gt;position&lt;/label&gt;&lt;div class=&quot;col-sm-10&quot;&gt;&lt;input class=&quot;form-control &quot; id=&quot;resume[data]_experiences___idx0___position&quot; name=&quot;resume[data][experiences][__idx0__][position]&quot; type=&quot;text&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;form-group required&quot;&gt;&lt;label class=&quot;control-label col-sm-2&quot; for=&quot;resume[data]_experiences___idx0___start_date&quot;&gt;start_date&lt;/label&gt;&lt;div class=&quot;col-sm-10&quot;&gt;&lt;select id=&quot;resume[data]_experiences___idx0___start_date_year&quot; name=&quot;resume[data][experiences][__idx0__][start_date][year]&quot;&gt;...&lt;/select&gt; / &lt;select id=&quot;resume[data]_experiences___idx0___start_date_month&quot; name=&quot;resume[data][experiences][__idx0__][start_date][month]&quot;&gt;...&lt;/select&gt; / &lt;select id=&quot;resume[data]_experiences___idx0___start_date_day&quot; name=&quot;resume[data][experiences][__idx0__][start_date][day]&quot;&gt;...&lt;/select&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;form-group required&quot;&gt;&lt;label class=&quot;control-label col-sm-2&quot; for=&quot;resume[data]_experiences___idx0___end_date&quot;&gt;end_date&lt;/label&gt;&lt;div class=&quot;col-sm-10&quot;&gt;&lt;select id=&quot;resume[data]_experiences___idx0___end_date_year&quot; name=&quot;resume[data][experiences][__idx0__][end_date][year]&quot;&gt;...&lt;/select&gt; / &lt;select id=&quot;resume[data]_experiences___idx0___end_date_month&quot; name=&quot;resume[data][experiences][__idx0__][end_date][month]&quot;&gt;...&lt;/select&gt; / &lt;select id=&quot;resume[data]_experiences___idx0___end_date_day&quot; name=&quot;resume[data][experiences][__idx0__][end_date][day]&quot;&gt;...&lt;/select&gt;&lt;/div&gt;&lt;/div&gt;&lt;input data-formex-id=&quot;&quot; id=&quot;resume[data]_experiences___idx0___formex_id&quot; name=&quot;resume[data][experiences][__idx0__][formex_id]&quot; type=&quot;hidden&quot;&gt;&lt;/div&gt;&lt;/div&gt;"><div class="formex-collection-items"></div><div class="form-group"><div class="col-sm-10 col-sm-offset-2"><button class="btn btn-default formex-collection-add " type="button">Add</button></div></div></div>
<input id="resume_data_id" name="resume[data][id]" type="hidden" value="">  <div class="form-group"><div class="col-sm-10 col-sm-offset-2"><button class="btn btn-default " type="submit">save</button></div></div>
</form>

The formex's javascript library is also loaded in app.js, I've checked. And there are no errors in the browser console when page is loaded and when I click the Add button.

Select validation without exceptions

When you send form with invalid select value, i.e. that value wasn't available in options of select, formex raises error. We don't want exceptions, it should simply display error in the form.

Use `mix format` and `credo` to make it easy to contribute to the repo

Would you be interested in a pull request that adds mix format formatting and credo linting to the codebase?

It shoulds be pretty simple:

By adding mix format, contributing would be easier because you don’t have to match the style of the author. And by adding credo it would remove dead code, warnings, unused alias, etc

Thanks for the great lib! Formex is saving us lots of time 👍

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.