Listing Cats

NameColorOwnerCategory
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