【问题标题】:Phoenix Form Field For Array Model Data Type数组模型数据类型的 Phoenix 表单字段
【发布时间】:2017-05-15 05:51:30
【问题描述】:

我正在使用令人惊叹的 Phoenix Web 框架,并试图弄清楚如何为具有数组字段的模型创建表单字段。

以下是模型中的示例字段: field :grateful, {:array, :string}

我试过生成这样的字段:

<%= inputs_for f, :grateful, fn fp -> %>
   <%= text_input fp, :grateful %>
<% end %>

但我收到此错误:无法从 Motivation.DailyPost 生成 :grateful 的输入。检查字段是否存在,它是 embeds_one、embeds_many、has_one、has_many、belongs_to 或 many_to_many 之一

如果我生成这样的字段:&lt;%= text_input fp, :grateful %&gt;,它会生成一个名称为:daily_post[grateful] 的表单字段,这实际上是行不通的。我需要daily_post[grateful][]

下面的代码有效,但保存后加载数据不起作用。所有数组值都合并到一个输入字段中。

  <div class="form-group" id="grateful-group">
    <%= label f, :grateful, class: "control-label" %>
      <%= text_input f, :grateful, name: "daily_post[grateful][]" %>
    <%= error_tag f, :grateful %>
    <input type="button" class="btn btn-success" id="add-grateful" value="add" />
    <script>
      window.onload = () => {
        $('#add-grateful').click((e) => {
          $('<input type="text" name="daily_post[grateful][]" />').appendTo("#grateful-group");
        })
      }
    </script>
  </div>

如何在 phoenix 中正确使用数组数据类型?

谢谢!

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    好的,我想我现在明白了。这就是我所做的:

    defmodule Motivation.InputHelpers do
      use Phoenix.HTML
    
      def array_input(form, field, attr \\ []) do
        values = Phoenix.HTML.Form.input_value(form, field) || [""]
        id = Phoenix.HTML.Form.input_id(form,field)
        content_tag :ul, id: container_id(id), data: [index: Enum.count(values) ] do
          values
          |> Enum.with_index()
          |> Enum.map(fn {k, v} ->
            form_elements(form, field, k, v)
          end)
        end
      end
    
      def array_add_button(form, field) do
        id = Phoenix.HTML.Form.input_id(form,field)
        # {:safe, content}
        content = form_elements(form,field,"","__name__")
          |> safe_to_string
          # |> html_escape
        data = [
          prototype: content,
          container: container_id(id)
        ];
        link("Add", to: "#",data: data, class: "add-form-field")
      end
    
      defp form_elements(form, field, k ,v) do
        type = Phoenix.HTML.Form.input_type(form, field)
        id = Phoenix.HTML.Form.input_id(form,field)
        new_id = id <> "_#{v}"
        input_opts = [
          name: new_field_name(form,field),
          value: k,
          id: new_id
        ]
        content_tag :li do
          [
            apply(Phoenix.HTML.Form, type, [form, field, input_opts]),
            link("Remove", to: "#", data: [id: new_id], class: "remove-form-field")
          ]
        end
      end
    
      defp container_id(id), do: id <> "_container"
    
      defp new_field_name(form, field) do
        Phoenix.HTML.Form.input_name(form, field) <> "[]"
      end
    
    end
    

    我将该文件导入我的 web.ex,然后我可以像这样打印数组字段:

    &lt;%= array_input f, :grateful %&gt;

    我也可以像这样为字段打印一个添加按钮:

    &lt;%= array_add_button f, :grateful %&gt;

    为了方便添加和删除字段,我编写了这个 javascript:

    window.onload = () => {
      const removeElement = ({target}) => {
        let el = document.getElementById(target.dataset.id);
        let li = el.parentNode;
        li.parentNode.removeChild(li);
      }
      Array.from(document.querySelectorAll(".remove-form-field"))
        .forEach(el => {
          el.onclick = (e) => {
            removeElement(e);
          }
        });
      Array.from(document.querySelectorAll(".add-form-field"))
        .forEach(el => {
          el.onclick = ({target}) => {
            let container = document.getElementById(target.dataset.container);
            let index = container.dataset.index;
            let newRow = target.dataset.prototype;
            container.insertAdjacentHTML('beforeend', newRow.replace(/__name__/g, index));
            container.dataset.index = parseInt(container.dataset.index) + 1;
            container.querySelectorAll('a.remove-form-field').forEach(el => {
              el.onclick = (e) => {
                removeElement(e);
              }
            })
          }
        });
    }
    

    【讨论】:

    • 太棒了!奇迹般有效!正是我需要的。
    【解决方案2】:

    也许这会为某人节省几个小时或更长时间。您可以将inputs_for 用于这样的数组类型:

    <%= f = form_for @changeset, Routes.user_path(@conn, :create), opts %>
      Name: <%= text_input f, :name %>
    
      <%= for friend_form <- inputs_for(f, :friends) do %>
        # for generating hidden inputs.
        <%= hidden_inputs_for(friend_form) %>
        <%= text_input friend_form, :name %>
      <% end %>
    </form>
    

    https://hexdocs.pm/phoenix_html/Phoenix.HTML.Form.html?#inputs_for/2

    【讨论】:

      猜你喜欢
      • 2014-04-15
      • 2016-04-28
      • 2021-01-29
      • 2021-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-11
      • 1970-01-01
      相关资源
      最近更新 更多