0

所以,我按照本教程创建动态表单:http ://blog.plataformatec.com.br/2016/09/dynamic-forms-with-phoenix/

好的,这是我的实际input_helpers.ex

defmodule Conts.InputHelpers do
  @moduledoc """
  Define <%= input f, :pass, type: :password_input %> syntax
  to create dynamic form inputs
  """

  use Phoenix.HTML

  alias Phoenix.HTML.Form, as: PhxForm
  import ContsWeb.ErrorHelpers, only: [error_tag: 2]

  @label_opts "basic-form-label"
  @input_opts "basic-form-input"

  def input(form, field, opts \\ []) do
    label_text = opts[:label] || humanize(field)
    type = opts[:type] || PhxForm.input_type(form, field)
    additional_classes = opts[:class] || ""

    label_opts = [class: @label_opts]

    input_opts = [
      class: "#{@input_opts} #{state_class(form, field)} #{additional_classes}",
      id: opts[:id]
    ]

    label_opts = if opts[:id], do: [for: opts[:for]] ++ label_opts, else: label_opts

    content_tag :fieldset do
      label = label(form, field, label_text, label_opts)
      input = input(type, form, field, input_opts)
      error = error_tag(form, field)
      error = if Enum.empty?(error), do: "", else: error

      [label, input, error]
    end
  end

  defp state_class(form, field) do
    cond do
      # The form was not yet submitted
      !form.action -> ""
      form.errors[field] -> "border-red-500"
      # we don't need any additional style at all
      # only with focus:within
      true -> ""
    end
  end

  # Implement clauses below for custom inputs.
  # defp input(:datepicker, form, field, input_opts) do
  #   raise "not yet implemented"
  # end
  defp input(:password_confirmation, form, field, input_opts) do
    apply(PhxForm, :password, [form, field, input_opts])
  end

  defp input(type, form, field, input_opts) do
    apply(PhxForm, type, [form, field, input_opts])
  end
end

在这个项目中,我们有一个cliente和一个user模式,具有 1-1 的关系!

在实时视图模板中,我做了:


<%= input f, :nome, label: "Nome completo", phx_debounce: "blur" %>

<%= input f, :telefone, label: "Número de telefone", phx_debounce: "blur", class: "mobile-masked" %>

<%= inputs_for f, :user, fn u -> %>
  <%= input u, :email, phx_debounce: "blur" %>

  <%= input u, :password, label: "Senha", phx_debounce: "blur" %>

  <%= input u, :password_confirmation, label: "Confirme a Senha", phx_debounce: "blur" %>
<% end %>

前两个字段来自变更集cliente,其他来自user变更集。当验证开始时,也就是用户开始输入输入,cliente的字段正确地应用了border-red-500类,但是user的字段没有!

我对其进行了调试,发现当它尝试验证用户变更集的任何字段时,在的state_class函数中input_helpers.ex,它属于该!form.acton子句。

我的问题是:我该如何处理这个嵌套的表单动作?为什么它属于上述cond条款?

这是一个 GIF 来演示这个问题: 在此处输入图像描述

4

1 回答 1

1

嵌套字段缺少该:action字段。在父窗体上,它通常是:validate.

有一种厚颜无耻的“hacky”方式来实现你想要的。只需从此更改您的 HTML:

<%= inputs_for f, :user, fn u -> %>

对此:

<%= for u <- inputs_for(f, :user) |> Enum.map(&Map.put(&1, :action, :validate)) do %>

:P

于 2021-04-15T14:00:16.990 回答