使用Phoenix.HTML.Form添加并显示错误消息“使用连接数据”

时间:2016-02-29 13:33:21

标签: elixir phoenix-framework

我有一个带有textarea的简单表单,用户可以在其中键入(或copy'n'paste)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(表单)或是否有其他方法可以获得?

3 个答案:

答案 0 :(得分:8)

在控制器模块中

创建一个包含操作

内错误的关键字列表
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 %>

答案 1 :(得分:1)

另一种方法是创建一个embeded_schema,您可以在其中定义包括验证在内的所有数据模型,而无需持久化到DB中,并依靠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 %>

答案 2 :(得分:-1)

我决定实现一个验证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

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