Phoenix Framework - 如何通过form_for填充地图字段?

时间:2016-01-20 12:46:40

标签: elixir phoenix-framework ecto

我正在尝试填充一个字段:params(来自Model / Schema),这是一张地图。我有一个工作form_for,我想填充这个:params映射到复选框,以便在提交表单时控制器将收到类似%{... params => %{"param1" => "true", "param2" => "false"}} ...

的内容

我看过inputs_for,但这似乎没有做我需要的东西,因为它依赖于嵌套的模式和模型,这意味着我需要为每个新的参数集创建一个新的模式(我需要如果参数发生变化,那些通用的东西不需要更改源代码。

<%= form_for @changeset, audit_audit_path(@conn, :new_tool_request, @audit.id),
       fn f -> %>

  <%= render LayoutView, "changeset_error.html", conn: @conn, changeset: @changeset, f: f %>

  <div class="form-group"><label>Tool</label>
    <%= select f, :toolname, tools %>
  </div>
  <div class="form-group"><label>Parameter 1</label>
    <%= checkbox f, :param1 %>
  </div>
  <div class="form-group"><label>Parameter 2</label>
    <%= checkbox f, :param2 %>
  </div>

  <div class="form-group"><label>Date of Execution</label>
    <%= datetime_select f, :date %>
  </div>
  <div class="form-group">
    <%= hidden_input f, :audit_id, value: @audit.id %>
  </div>

  <%= submit "Request", class: "btn btn-primary" %>
<% end %>

因此,我需要将所有这些参数放入地图中,而不是使用param1param2的复选框。如果使用不同的参数复选框呈现另一个表单,则必须填充它而不与模式有任何关系。

谢谢!

2 个答案:

答案 0 :(得分:0)

事实上,我认为,如果情况如此:

  schema "checkmapss" do
    field :name, :string
    field :options, :map

    timestamps()
  end

我们需要做的是在form.html.eex:

  <div class="form-group">
    <%= label f, :options, class: "control-label" %>
    <%= text_input f, :options_one, name: "checkmap[options][one]", class: "form-control" %>
    <%= error_tag f, :options %>
  </div>
  <div class="form-group">
    <%= label f, :options, class: "control-label" %>
    <%= text_input f, :options_two, name: "checkmap[options][two]", class: "form-control" %>
    <%= error_tag f, :options %>
  </div>

然后变更集功能将帮助我们完成其他任务。

答案 1 :(得分:-1)

我遇到了同样的问题,但使用简单的 HTML 表单和长生不老药,ecto 模式匹配让它可以很好地轻松工作。

Ecto 架构定义

schema "stuff" do
  field :name, :string
  field :settings, :map
end

控制器或资源 :edit 操作

changeset = StuffContext.change_stuff(stuff)

在您的模板/表单中

<%= form_for @changeset, Routes.stuff_path(@conn, :save, @stuff), fn f -> %>
   ...
   <%= label f, :currency %>
   <%= text_input f, :stuff_currency, name: "stuff[settings][currency]", 
   value: @stuff.settings["currency"], required: true %>
   <%= error_tag f, :settings %> <-- Important errors come from ecto validation logic we put into changeset, not the made up currency
   ...

然后在您的控制器中 :save 操作

def save(conn, %{"id" => id, "stuff" => stuff_params}) do
  stuff = StuffContext.get(id)
  ...
  IO.inspect(stuff_params) ->

  %{"name" => "welcome", "settings" => %{"currency" => "USD"}}
  ...
  StuffContext.update_stuff(stuff, stuff_params)