如何将Phoenix.HTML单选按钮状态保留到PostgreSQL数据库,同时仍然使它们成为一个组?

时间:2017-02-19 23:20:02

标签: html5 elixir phoenix-framework

我为新用户提供了此数据库架构。

defmodule XYZ.User do
  use XYZ.Web, :model

  schema "users" do
    field :lawyer, :boolean
    field :firm, :boolean
    field :first_name, :string
    field :last_name, :string
    field :phone, :string
    field :email, :string

    timestamps
  end

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, [:lawyer, :firm, :first_name, :last_name, :phone, :email])
    |> validate_required([:first_name, :last_name, :phone, :email])
  end

end

UserController通过创建新的用户变更集并将其传递到Web视图/模板进行渲染来处理/ users / new。

defmodule XYZ.UserController do
  use XYZ.Web, :controller

  def new(conn, _params) do
    changeset = User.changeset(%User{})
    render conn, "new.html", changeset: changeset
  end

new.html.eex模板使用Phoenix.HTML帮助函数将律师/公司渲染为两个单选按钮。

<%= form_for @changeset, user_path(@conn, :create), fn f -> %>
  <div class="form-group">
    <%= radio_button f, :lawyer, "true", checked: "checked %>
    <%= label f, :user_lawyer, "Lawyer" %>
    <%= radio_button f, :firm, "true" %>
    <%= label f, :user_firm, "Firm" %>
  </div> 
  ...

上面源代码的呈现HTML如下所示。

div class="form-group">
  <input checked="checked" id="user_lawyer_true" name="user[lawyer]"  type="radio" value="true">
  <label for="user_user_lawyer">Lawyer</label>
  <input id="user_firm_true" name="user[firm]" type="radio" value="true">
  <label for="user_user_firm">Firm</label>
div>

使用上面的代码提交表单会将true值保存到数据库记录中与表单上选中的单选按钮对应的列。

但是,这两个单选按钮不能作为一个组发挥作用。当只应选择一个时,可以选择两个单选按钮。

更改Phoenix.HTML辅助函数,添加名称:&#34;输入&#34;对于选项,将对两个单选按钮进行分组,但在提交表单时,所选单选按钮的真实值不会保留到数据库中。

这里是修改过的帮助函数。

<%= form_for @changeset, user_path(@conn, :create), fn f -> %>
  <div class="form-group">
    <%= radio_button f, :lawyer, "true",  name: "type", checked: "checked" %>
    <%= label f, :user_lawyer, "Lawyer" %>
    <%= radio_button f, :firm, "true", name: "type" %>
    <%= label f, :user_firm, "Firm" %>
  </div>
  ...

这里是上面源代码的呈现HTML。

div class="form-group">
  <input checked="checked" id="user_lawyer_true" name="type" type="radio" value="true">
  <label for="user_user_lawyer">Lawyer</label>
  <input id="user_firm_true" name="type" type="radio" value="true">
  <label for="user_user_firm">Firm</label>
/div>

如何使两个单选按钮表现为一个组,同时仍然将正确的值保存到数据库中?

我使用以下版本的软件:

  • Elixir v1.3.4
  • Phoenix v1.2.1
  • PostgreSQL v9.5.4

提前致谢。

-----解决方案-----

我最终实现了一个@cpjolicoeur建议,修改了用户模式,删除了布尔律师公司字段,并添加了一个名为 type的字符串字段

schema "users" do
  field :type, :string
  field :first_name, :string
  field :last_name, :string
  field :phone, :string
  field :email, :string

  timestamps
end

然后我修改了new.html.eex模板:

<%= form_for @changeset, user_path(@conn, :create), fn f -> %>
  <div class="form-group">
    <%= radio_button f, :type, "lawyer", checked: "checked" %>
    <%= label f, :user_lawyer, "Lawyer" %>
    <%= radio_button f, :type, "firm" %>
    <%= label f, :user_firm, "Firm" %>
  </div>
  ...

通过这些更改,选择单选按钮,&#34;律师&#34;或者&#34;公司&#34;,在创建新用户时保存到类型字段。

1 个答案:

答案 0 :(得分:1)

我认为可能存在一些可能性。

首先,您可以将value元素的<radio />属性更改为具有不同的值。现在它们都具有值true,这意味着无论选择哪个,发送到控制器的“类型”参数将始终具有值true,这意味着您无法知道选择了哪个单选按钮。您可以将值更改为value="firm"value="lawyer",以便控制器中的“类型”参数将保持字符串“firm”或“lawyer”,而不是始终为“true” ”

但是,如果真的是相互排斥的选项,那么第二种选择就会浮现在脑海中。只需在数据库中存储一列而不是两列。这可能有几种可能的咒语。

  • 如果他们是律师,那么booleanlawyer可能是真的,如果是假的话,你知道他们是firm。在这种情况下,lawyer的单选按钮会有value="true"firm的单选按钮会有value="false"
  • 将数据库字段更改为enum类型,您可以在其中将值映射到已知类型(律师,公司等等)。如果需要,这样您还可以在以后扩展类型列表至。然后您的单选按钮值只是您正在使用的“枚举”值。