A status for tasks, from a list of colored options, checked on the server as in the browser.
1. Install
Add {:erabi, "~> 0.1"} to your deps, then:
mix deps.get
mix erabi.install
The installer adds the Erabi hook to assets/js/app.js and the style
sheet to assets/css/app.css (see the README for the manual steps).
2. The options
defmodule MyApp.Tasks do
def statuses do
[
%{value: :todo, label: "To do", color: :gray},
%{value: :doing, label: "In progress", color: :yellow},
%{value: :done, label: "Done", color: :green}
]
end
end3. The changeset
The schema's field is an Ecto.Enum, as it would be for a <select>;
Erabi.Changeset.validate_choice/4 checks the picker's rules on the
server:
schema "tasks" do
field :status, Ecto.Enum, values: [:todo, :doing, :done]
end
def changeset(task, params) do
task
|> cast(params, [:status])
|> Erabi.Changeset.validate_choice(:status, [required: true], options: MyApp.Tasks.statuses())
end4. The picker
Import the components in the html_helpers of your web module:
import Erabi.Componentsand put the picker in the form:
<.form for={@form} id="task-form" phx-change="validate" phx-submit="save">
<label for={@form[:status].id}>Status</label>
<.select field={@form[:status]} options={MyApp.Tasks.statuses()} required />
<button>Save</button>
</.form>The picker posts task[status] as a <select> would: phx-change and
phx-submit get it as they are. Before the hook mounts, and with
JavaScript off, it is that <select>.
5. A test
import Erabi.Test
test "a task is done", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/tasks/1")
assert choices(view, "task_status_picker") == ["To do", "In progress", "Done"]
html = choose(view, "task_status_picker", :done)
assert html =~ "Done"
end