У меня есть схема базы данных для нового пользователя.
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 обрабатывает / users / new, создавая новый набор изменений User и передавая его в веб-представление / шаблон для рендеринга.
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, добавление name: "type" к параметрам, сгруппирует два переключателя, но истинное значение выбранного переключателя не сохраняется в базе данных при отправке формы.
Вот модифицированные вспомогательные функции.
<%= 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>
Как заставить два переключателя работать как группа, сохраняя при этом правильные значения в базе данных?
Я использую следующие версии программного обеспечения:
- Эликсир v1.3.4
- Феникс v1.2.1
- PostgreSQL v9.5.4
Заранее спасибо.
----- РЕШЕНИЕ -----
В итоге я реализовал одно из предложений @cpjolicoeur, изменив схему User, удалив логические поля lawyer и firm и добавив одно строковое поле с именем type em >.
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>
...
С этими изменениями выбор переключателя «юрист» или «фирма» сохраняется в поле type при создании нового пользователя.