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 |
Allows for a shareable URL such as liveviewbasics.com/basic-eleven?q=ar&category=Real&sort_by=Color .
Documentation:
https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#c:handle_params/3
https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_patch/2
NOTE: reference the Setup section for generating the Animals context and adding the Cats to the database used in this example.
scope "/", LiveViewBasicsWeb do
pipe_through :browser
live "/cats", CatLive.Index, :index
end
defmodule LiveViewBasicsWeb.CatLive.Index do
use LiveViewBasicsWeb, :live_view
alias LiveViewBasics.Animals
def mount(_params, _session, socket) do
{:ok, socket}
end
def handle_params(params, _uri, socket) do
socket =
socket
|> stream(:cats, Animals.filter_cats(params), reset: true)
|> assign(:form, to_form(params))
{:noreply, socket}
end
def render(assigns) do
~H"""
<Layouts.app flash={@flash}>
<.header>
Listing Cats
</.header>
<div class="mb-2">
<.form
class="sm:flex justify-left gap-4 items-center"
for={@form}
id="filter-form"
phx-change="filter"
phx-submit="filter"
>
<.input field={@form[:q]} placeholder="Search..." autocomplete="off" phx-debounce="500" />
<.input
type="select"
field={@form[:category]}
prompt="Category"
options={["Real", "Fictional"]}
/>
<.input
type="select"
field={@form[:sort_by]}
prompt="Sort By"
options={["Name", "Color", "Owner"]}
/>
<.link class="mb-2" patch={~p"/cats"}>
Reset
</.link>
</.form>
<.table id="cats" rows={@streams.cats}>
<: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>
</.table>
</div>
<Layouts.app flash={@flash}>
"""
end
def handle_event("filter", params, socket) do
params =
params
|> Map.take(~w(q category sort_by))
|> Map.reject(fn {_, v} -> v == "" end)
socket = push_patch(socket, to: ~p"/cats?#{params}")
{:noreply, socket}
end
end
def filter_cats(filter) do
Cat
|> where([c], ilike(c.name, ^"%#{filter["q"]}%"))
|> with_category(filter["category"])
|> sort(filter["sort_by"])
|> Repo.all()
end
defp with_category(query, category) when category in ~w(Real Fictional) do
where(query, category: ^category)
end
defp with_category(query, _), do: query
defp sort(query, "Name"), do: order_by(query, :name)
defp sort(query, "Color"), do: order_by(query, :color)
defp sort(query, "Owner"), do: order_by(query, :owner)
defp sort(query, _), do: order_by(query, :id)