【问题标题】:Phoenix Framework - How to populate a map field through a form_for?Phoenix Framework - 如何通过 form_for 填充地图字段?
【发布时间】:2021-03-11 03:06:53
【问题描述】:

我正在尝试填充一个字段 :params(来自模型/架构),它是一个地图。我有一个工作的 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 设置这些复选框。如果另一个表单使用不同的参数复选框呈现,则它必须在与架构没有任何关系的情况下填充。

谢谢!

【问题讨论】:

  • 如果我的问题是正确的,我想你只需要为它们生成一个名称空间“params”的名称属性,比如&lt;%= checkbox f, :param1, name: "params[param1]" %&gt;&lt;%= checkbox f, :param2, name: "params[param2]" %&gt;,但我相信它有form_for应该自动完成。
  • 这不是我想要的,但它确实有效!谢谢你。仅供参考,如果您按照@JustMichael 的建议进行操作,您将提交另一个表单/地图,在这种情况下,名称为“params”。在您的控制器中,只需定义一个接收 def action_to_use(conn, "form" =&gt; form, "params" =&gt; params 等参数的函数,您将获得使用命名空间创建的第二个表单。

标签: elixir phoenix-framework ecto


【解决方案1】:

事实上,我认为,如果在这种情况下:

  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>

那么变更集功能将帮助我们完成其他事情。

【讨论】:

    【解决方案2】:

    我也遇到了同样的问题,但是使用简单的 HTML 表单和 elixir,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)
    

    【讨论】:

      猜你喜欢
      • 2016-03-20
      • 1970-01-01
      • 2017-07-21
      • 2018-12-28
      • 2011-03-07
      • 1970-01-01
      • 2015-11-21
      • 2013-09-04
      • 2011-11-02
      相关资源
      最近更新 更多