【问题标题】:Add and show an error message with Phoenix.HTML.Form "With connection data"使用 Phoenix.HTML.Form "With connection data" 添加并显示错误消息
【发布时间】:2018-12-23 17:12:04
【问题描述】:

我有一个带有文本区域的简单表单,用户可以在其中输入(或复制'n'粘贴)一个 json 字符串。表单将发送到我的控制器操作,我将验证 json 字符串,如果没问题,我将创建一些记录,一切都很好。

要将表单发送到我的控制器操作,我目前使用Phoenix.HTML.Form“带有连接数据”,因此我没有模型/变更集。

<%= form_for @conn, @action, [as: :match], fn f -> %>
  <%= textarea f, :json, rows: 20 %>
  <%#= error_tag @changeset, f, :json %>
<% end %>

如果 json 由于某种原因无效,我想再次呈现表单并显示错误消息。 error_tag 是一个视图辅助方法,如果有变更集,它将在字段中显示错误。正因为如此,它现在被注释掉了。

def error_tag(form, field) do
  if error = form.errors[field] do
    content_tag :span, (humanize(field) <> " " <> translate_error(error)), class: "help-block"
  end
end

def error_tag(changeset, form, field) do
  if changeset.action do
    error_tag(form, field)
  end
end

添加错误以便我可以在表单字段中显示它们的正确方法是什么。我必须将错误添加到@connf(表单)还是有其他方法可以得到?

【问题讨论】:

  • 我认为您可以在重新呈现表单之前将错误分配给控制器中的连接并访问表单中的错误,因为无论如何您都将连接传递给模板。

标签: elixir phoenix-framework


【解决方案1】:

在您的控制器模块中

创建一个关键字列表,其中包含操作中的错误

errors = [field: "error message"]

然后在调用render方法时传入

render(conn, "template.html", errors: errors)

在您的视图模块中

添加辅助函数以从关键字列表中提取和格式化消息

def error_tag(errors, field) when is_list(errors) and is_atom(field) do
  case Keyword.fetch(errors, field) do
    {:ok, message} -> content_tag :span, (humanize(field) <> " " <> translate_error(message)), class: "help-block"
    :error -> html_escape("")
  end
end

在您的模板文件中

显示错误信息

<%= form_for @conn, @action, [as: :match], fn f -> %>
  <%= textarea f, :json, rows: 20 %>
  <%= error_tag @errors, :json %>
<% end %>

【讨论】:

  • 感谢您的帮助。我试过了,但有很多东西我必须重新实现或扩展。这会产生丑陋的代码。我尝试了很多,经过一些实验后,我决定像使用模型一样使用 Ecto.Changeset。
  • Phoenix 1.2.3 Phoenix.ErrorHelpers.translate_error({msg, opt}),然后 translate_error(msg) 将引发 在 Phoenix.ErrorHelpers.translate_error/1 中没有函数子句匹配
【解决方案2】:

另一种方法是创建一个embeded_schema,您可以在其中定义包括验证在内的所有数据模型,而无需保留到数据库中,并依赖 Phoenix 中提供的验证/错误管理。 José Valim explains 如何使用这种方法。

您只需以这种方式创建架构:

data  = %{}
types = %{first_name: :string, last_name: :string, email: :string}

changeset =
  {data, types} # The data+types tuple is equivalent to %Registration{}
  |> Ecto.Changeset.cast(params["sign_up"], Map.keys(types))
  |> validate_required(...)
  |> validate_length(...)

然后照常显示错误:

<%= error_tag f, :first_name %>

【讨论】:

    【解决方案3】:

    我决定实现一个验证 json 字符串的模块。模块方法changeset 返回一个Ecto.Changeset,我在其中添加了我的自定义错误。私有 validate_json 方法检查 json 模式和内容。毕竟我将更改和参数设置为表单中的给定参数并且我设置有效?不管我有没有错误。

    def changeset(required_fields, json_field, params) do
      changeset =
        %Ecto.Changeset{model: %MyApp.ModelName{}}
          |> Ecto.Changeset.cast(params, required_fields, ~w())
          |> validate_json(json_field, params)
      %Ecto.Changeset{changeset | changes: params, params: params, valid?: Enum.count(changeset.errors) == 0}
    end
    

    通过这种方式,我可以保持我的视图和部分内容不变,并且表单和所有辅助方法都可以像以前一样与我的变更集一起使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-30
      • 2011-10-31
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多