Listing Cats
Name | Color | Owner | Category |
---|---|---|---|
Marley | Black | Brian | Real |
MJ | Tortoiseshell | Brian | Real |
Mr. Business | Gray | Gayle | Fictional |
Garfield | Orange | Jon | Fictional |
Goose | Orange | Wendy | Fictional |
NOTE: reference the Setup section for generating the Animals context and adding the Cats to the database used in this example.
NOTE: while you can click the "New Cat" button and interact with the form, creating cats is disabled for this preview. The code below will still create new cats.
scope "/", LiveViewBasicsWeb do
pipe_through :browser
live "/cats", CatLive.Index, :index
live "/cats/new", CatLive.Form, :new
live "/cats/:id", CatLive.Show, :show
end
defmodule LiveViewBasicsWeb.CatLive.Index do
use LiveViewBasicsWeb, :live_view
alias LiveViewBasics.Animals
def mount(_params, _session, socket) do
socket = stream(socket, :cats, Animals.list_cats())
{:ok, socket}
end
def render(assigns) do
~H"""
<Layouts.app flash={@flash}>
<.header>
Listing Cats
<:actions>
<.button navigate={~p"/cats/new"}>
<.icon name="hero-plus" /> New Cat
</.button>
</:actions>
</.header>
<div class="mb-2">
<.table
id="cats"
rows={@streams.cats}
row_click={fn {_id, cat} -> JS.navigate(~p"/cats/#{cat}") end}
>
<:col :let={{_id, cat}} label="Name">{cat.name}</:col>
<:col :let={{_id, cat}} label="Color">{cat.color}</:col>
<:col :let={{_id, cat}} label="Owner">{cat.owner}</:col>
<:col :let={{_id, cat}} label="Category">{cat.category}</:col>
<:action :let={{_id, cat}}>
<div class="sr-only">
<.link navigate={~p"/cats/#{cat}"}>Show</.link>
</div>
</:action>
</.table>
</div>
<Layouts.app flash={@flash}>
"""
end
end
defmodule LiveViewBasicsWeb.CatLive.Show do
use LiveViewBasicsWeb, :live_view
alias LiveViewBasics.Animals
def mount(%{"id" => id}, _session, socket) do
socket = assign(socket, :cat, Animals.get_cat!(id))
{:ok, socket}
end
def render(assigns) do
~H"""
<Layouts.app flash={@flash}>
<.header>
Cat {@cat.id}
</.header>
<div class="mb-2">
<.list>
<:item title="Name">{@cat.name}</:item>
<:item title="Color">{@cat.color}</:item>
<:item title="Owner">{@cat.owner}</:item>
<:item title="Owner">{@cat.category}</:item>
</.list>
</div>
<Layouts.app flash={@flash}>
"""
end
end
defmodule LiveViewBasicsWeb.CatLive.Form do
use LiveViewBasicsWeb, :live_view
alias LiveViewBasics.Animals
alias LiveViewBasics.Animals.Cat
def mount(params, _sessions, socket) do
socket = apply_action(socket, socket.assigns.live_action, params)
{:ok, socket}
end
def render(assigns) do
~H"""
<.header>
Cat Form
</.header>
<div class="mb-2">
<.form for={@form} id="cat-form" phx-change="validate" phx-submit="save">
<.input field={@form[:name]} type="text" label="Name" />
<.input field={@form[:color]} type="text" label="Color" />
<.input field={@form[:owner]} type="text" label="Owner" />
<.input field={@form[:category]} type="text" label="Category" />
<footer>
<.button phx-disable-with="Saving...">Save Cat</.button>
</footer>
</.form>
</div>
"""
end
def handle_event("validate", %{"cat" => cat_params}, socket) do
changeset = Animals.change_cat(socket.assigns.cat, cat_params)
{:noreply, assign(socket, form: to_form(changeset, action: :validate))}
end
def handle_event("save", %{"cat" => cat_params}, socket) do
save_cat(socket, socket.assigns.live_action, cat_params)
end
defp apply_action(socket, :new, _params) do
cat = %Cat{}
socket
|> assign(:cat, cat)
|> assign(:form, to_form(Animals.change_cat(cat)))
end
defp save_cat(socket, :new, cat_params) do
case Animals.create_cat(cat_params) do
{:ok, cat} ->
socket =
socket
|> put_flash(:info, "Cat created successfully")
|> push_navigate(to: ~p"/cats/#{cat}")
{:noreply, socket}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, form: to_form(changeset))}
end
end
end
# This code already exists if you ran the context generator in the Setup
def create_cat(attrs) do
%Cat{}
|> Cat.changeset(attrs)
|> Repo.insert()
end